【问题标题】:Handle n menu items in template engine处理模板引擎中的 n 个菜单项
【发布时间】:2013-10-24 09:42:32
【问题描述】:

我需要创建 N 个菜单项,可能有 N 个子项。

这适用于一个级别。

items = {'link1': 'value1', 
         'link2': 'value2', 
         'link3': 'value3'
         }

<nav id="menu">
    <ul>
        {% for key in items %}
        <li>
           <a href="{{ escape(key) }}"> {{ escape(items[key]) }}</a>
        </li
       {% end %}
    </ul>
</nav>

这将输出:

<nav id="menu">
    <ul>
        <li>
            <a href="link1"> value1</a>
        </li>
        <li>
            <a href="link2"> value2</a>
        </li>
        <li>
            <a href="link3"> value3</a>
        </li>
    </ul>
</nav>

但是如果我有这样一个更复杂的结构,如何处理呢?

level 1
   level 1.1
   level 1.2
   level 1.3
level 2
   level 2.1
      level 2.1.1
          level 2.1.1.1
      level 2.1.2
level 3
   level 3.1
   level 3.2

【问题讨论】:

  • 好问题,简洁的例子,展示了尝试。谢谢。但我认为,您将不得不创建一个自定义过滤器。
  • 您使用的是什么模板引擎?我有一个 django templatetag 解决类似任务的例子,但它是你要找的吗?
  • @alko, tornado.template tornadoweb.org/en/stable/template.html

标签: python template-engine


【解决方案1】:

改为使用 dicts 列表,并允许每个 dicts 有一个“children”键。 “两级”菜单示例:

items = [
    {'label': 'label1', 
     'link': 'link1',
     'children': [
         {'label':'label1.1', 'link': 'link1.1'}, 
         {'label':'label1.2', 'link': 'link1.2'} 
         ]
     },
    {'label': 'label2', 
     'link': 'link2',
     'children': [
         {'label':'label2.1', 'link': 'link2.1'}, 
         {'label':'label2.2', 'link': 'link2.2'} 
         ]
     },
    # etc
    ]

然后在你的模板中:

<nav id="menu">
    <ul>
        {% for item in items %}
        <li>
           <a href="{{ escape(item['link']) }}"> {{ escape(item['label']) }}</a>
           {% if 'children' in item %}
           <ul>
             {% for child in item['children'] %}
             <li>
               <a href="{{ escape(child['link']) }}"> {{ escape(child['label']) }}</a>
             </li>
             {% end %}
           </ul>
           {% end %}
        </li
       {% end %}
    </ul>
</nav>

如果您希望能够处理任意深度,则需要在模板中使用一些递归机制,但由于我不知道您使用的是什么模板引擎,所以在这里我无能为力。

【讨论】:

  • 更合理的方法。仍在研究一种迭代嵌套结构的方法。问题是大多数解决方案都是递归的,这有点难以做到。
  • @loops:是的,我可以,但我不会——这是微不足道的,这是你的工作,不是我的。只是一个提示:不要在你的数据结构中使用“children_0”/“children_1”,而只是“children”,你确实想要一个统一的结构,无论深度如何。
  • @loops:哦,是的:如果您的 teplate 引擎有任何类型的包含机制(应该是这种情况),那么解决“任意深度”问题也是微不足道的。与任何树结构一样,递归是您的朋友。
  • @loops:我不知道什么是“PHP 程序员”。你要么是程序员,要么不是。如果你能用 PHP 解决这个“问题”,你可以用 Python 和 tornado.template 轻松解决。
【解决方案2】:

有一种方法可以进行这种迭代,那就是了解它的类型。所以,假设你有列表,在这个列表中你有字符串和列表。所以,这就是我的做法:

{% if key.get_type == "list" %}
    {% for var in key %}
     ... (this will only work for as many levels as you define)

【讨论】:

    【解决方案3】:

    要将输出视为嵌套列表,请使用以下命令: (我假设您已经拥有类似格式的 items 字典。)

    items = [
    {'link': 'link1','value': 'value1',
     'sub_items': [
           {'link':'link1.1','value':'value1.1'},
           {'link':'link1.2','value':'value1.2'},
           {'link':'link1.3','value':'value1.3'},
      ]
     },
     {'link': 'link2','value': 'value2',
      'sub_items': [
           {'link':'link2.1','value':'value2.1',
            'sub_items': [
                {'link':'link2.1.1','value':'value2.1.1',
                 'sub_items': [
                    {'link':'link2.1','value':'value2.1.1.1'}
                 ]
                }
            ]
           }
      ]
     },
     {'link': 'link3','value': 'value3',
      'sub_items': [
           {'link':'link3.1','value':'value3.1'}
      ]
     }
    ]
    

    在您的模板中:

    <nav id="menu">
    <ul>
    {% for item in items %}
      <li>
        <a href="{{ item.link }}"> {{ item.value }}</a>
        {% if item.sub_items %}
          <ul>
          {% for item2 in item.sub_items %}
            <li>
            <a href="{{ item2.link }}"> {{ item2.value }}</a>
            {% if item2.sub_items %}
              <ul>
              {% for item3 in item2.sub_items %}
                <li>
                <a href="{{ item3.link }}"> {{ item3.value }}</a>
                {% if item3.sub_items %}
                  <ul>
                    {% for item4 in item3.sub_items %}
                      <li>
                        <a href="{{ item4.link }}"> {{ item4.value }}</a>
                      </li>
                    {% endfor %}
                  </ul>
                {% endif %}
                </li>
              {%endfor%}
              </ul>
            {% endif %}
            </li>
          {%endfor%}
          </ul>
        {% endif %}
      </li>
    {%endfor%}
    </ul>
    </nav>
    

    它将产生所需的输出。

    【讨论】:

    • endif 不受支持。无论如何替换为最终作品,但我仍然得到,如果 item2["sub_items"]: # index.html:30 KeyError: 'sub_items'
    • @loops 我已经更新了我的答案。由于模板引擎的差异,该错误即将到来。您可以根据自己的语法更新 html。
    猜你喜欢
    • 2013-07-16
    • 1970-01-01
    • 2020-06-16
    • 2011-11-24
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    相关资源
    最近更新 更多