如何在Django模板中渲染树形结构(递归)?

76 投票
10 回答
40772 浏览
提问于 2025-04-10 23:56

我在内存中有一个树形结构,想用Django模板把它显示成HTML。

class Node():
  name = "node name"
  children = []

这里会有一个对象叫做 root,它是一个 Node(节点),而 children 是一个包含多个 Node 的列表。这个 root 会在模板的内容中传递过来。

我找到了一篇关于如何实现这个的讨论,链接在这里 this,但发帖的人提到在生产环境中这样做可能不太好。

有没有人知道更好的方法呢?

10 个回答

50

我来得太晚了。
你们都用了太多不必要的 with 标签,这里是我做递归的方法:

在“主”模板中:

<!-- lets say that menu_list is already defined -->
<ul>
    {% include "menu.html" %}
</ul>

然后在 menu.html 中:

{% for menu in menu_list %}
    <li>
        {{ menu.name }}
        {% if menu.submenus|length %}
            <ul>
                {% include "menu.html" with menu_list=menu.submenus %}
            </ul>
        {% endif %}
    </li>
{% endfor %}
85

使用 with 模板标签,我可以创建树形/递归列表。

示例代码:

主模板:假设 'all_root_elems' 是一个包含一个或多个树根的列表

<ul>
{%for node in all_root_elems %} 
    {%include "tree_view_template.html" %}
{%endfor%}
</ul>

tree_view_template.html 渲染嵌套的 ulli,并使用 node 模板变量,如下所示:

<li> {{node.name}}
    {%if node.has_childs %}
        <ul>
         {%for ch in node.all_childs %}
              {%with node=ch template_name="tree_view_template.html" %}
                   {%include template_name%}
              {%endwith%}
         {%endfor%}
         </ul>
    {%endif%}
</li>
29

我觉得最简单的答案就是:“别这么做”。

你应该考虑在你的 视图 代码中把事情理清楚,这样就可以简单地在模板中逐个处理缩进和取消缩进。我想我会在遍历树的时候,把缩进和取消缩进的内容添加到一个列表中,然后把这个“旅行日志”列表传给模板。这样,模板就可以根据这个列表插入 <li></li>,从而创建出递归的结构。

我也很确定,递归地包含模板文件其实是一种 错误 的做法……

撰写回答