Django模板迭代嵌套列表

时间:2014-06-29 05:29:21

标签: python django django-templates

在Django中,我们如何在模板中迭代[[1,[2,[3]],[4,[]]],[2,[3]]]之类的内容。

请注意,以上只是一个随机的例子。列表的每个元素可以在其中进一步包含任意数量的嵌套列表。我想遍历内部的每个值,并且还想知道什么是父级,以便我们可以适当地设置HTML的样式。

虽然有一种方法可以通过递归在视图中生成HTML并在模板中使用相应的变量,但这会使django模板和视图依赖,这是不需要的(loose coupling principle)。使用视图的一个示例是here,但模板系统本身的表示将优于此类实现。

2 个答案:

答案 0 :(得分:1)

Django模板不是为处理复杂逻辑而设计的 例如,您 无法 使用include标记来编写嵌套逻辑:

# foo.html
{% if nodes|iterable %}
<ul>
{% for x in nodes %}
  {% include "foo.html" with nodes=x %}
{% endfor %}
</ul>
{% else %}
<li>{{ nodes }}</li>
{% endif %}

因为Django模板节点在渲染之前会被解析和编译,并且上面代码的编译可能会陷入循环并且通过达到最大递归深度而失败。

通常情况下,就像{% nested nodes %}一样,模板标签就像一个视图,但属于Django模板的范围,就是你所需要的。

此外,您可以通过过滤器将数据转换为平面数据,然后轻松循环:

{% for x in nodes|nested_to_flat %}
{% if x.start_nodes %}<ul>{% endif %}
{% if x.end_nodes %}</ul>{% endif %}
{% if x.start_node %}<li>{% endif %}
{% if x.end_node %}</li>{% endif %}
{% if x.is_data %}{{ x.data }}{% endif %}
{% endfor %}

# nested_to_flat
@register.filter
def nested_to_flat(nodes):
    if isinstance(nodes, list):
        yield {'start_nodes': True}
        for node in nodes:
            yield {'start_node': True}
            for i in nested_to_flat(node):
                yield i
            yield {'end_node': True}
        yield {'end_nodes': True}
    else:
        yield {'data': nodes, 'is_data': True}

这类似于渲染mptt树或线程注释的想法。

答案 1 :(得分:0)

如上所述,django-mptt中提到的是一个预先制定的解决方案,它应该非常适合您的问题。

如果您想推送自己的模板标签,可以查看django文档中的custom template tags

一些提示:

  • 通过创建具有无限嵌套的标记,您可能会遇到可用性问题,因为屏幕空间有限,并且可能因此考虑限制数据结构的深度。如果您必须坚持使用数据结构,则可以根据级别数在模板中使用for循环。
  • 如果您更喜欢内置模板标签,那么使用嵌套字典列表(包含重要订单的列表)会更好,这也更容易在模板中阅读。
  • 松散耦合作为一般原则是好的。但由于Django中的视图主要目的是为模板准备数据结构,因此无法将其完全分离。