如何使用django模板渲染树结构(递归)?

时间:2008-08-28 11:43:10

标签: python django

我在内存中有一个树结构,我希望使用Django模板在HTML中呈现。

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

某些对象rootNode,而childrenNode的列表。 root将在模板的内容中传递。

我已经找到了this关于如何实现这一目标的讨论,但是海报表明这在生产环境中可能并不好。

有人知道更好的方法吗?

10 个答案:

答案 0 :(得分:67)

使用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>

答案 1 :(得分:27)

我认为规范的答案是:“不要”。

你应该做的事情是解开 view 代码中的东西,所以这只是在模板中迭代(in | de)凹痕的问题。我想我会通过在列表中附加缩进和dedents来实现它,同时通过树递归然后将“travelogue”列表发送到模板。 (然后模板将从该列表中插入<li></li>,创建递归结构并“理解”它。)

我也非常确定递归包含模板文件实际上是错误的方式...

答案 2 :(得分:20)

这可能比你需要的更多,但是有一个名为'mptt'的django模块 - 它在sql数据库中存储一个分层树结构,并包含在视图代码中显示的模板。你或许可以在那里找到有用的东西。

这是链接:django-mptt

答案 3 :(得分:12)

我太晚了) 所有人都使用了这么多不必要的 标签,这就是我的回复方式:

在主模板中:

<!-- 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 %}

答案 4 :(得分:11)

是的,你可以做到。这是一个小技巧, 将文件名作为变量传递给{%include%}:

{% with template_name="file/to_include.html" %}
{% include template_name %}
{% endwith %}

答案 5 :(得分:9)

Django为这个确切的场景提供了一个内置的模板助手:

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#unordered-list

答案 6 :(得分:8)

我有同样的问题,我写了一个模板标签。我知道还有其他类似的标签,但我还是需要学习制作自定义标签:)我认为结果非常好。

阅读文档字符串以获取使用说明。

github.com/skid/django-recurse

答案 7 :(得分:0)

没有人喜欢dicts吗?我可能在这里遗漏了一些东西,但这似乎是设置菜单最自然的方式。使用键作为条目和值作为链接在DIV / NAV中弹出它然后离开你去!

从您的基地

# Base.html
<nav>
{% with dict=contents template="treedict.html" %}
 {% include template %}
{% endwith %}
<nav>

称之为

# TreeDict.html
<ul>
{% for key,val in dict.items %}
 {% if val.items %}
  <li>{{ key }}</li>
  {%with dict=val template="treedict.html" %}
   {%include template%}
  {%endwith%}
 {% else %} 
  <li><a href="{{ val }}">{{ key }}</a></li>
 {% endif %}
{% endfor %} 
</ul>

它没有尝试过默认或订购但也许你有吗?

答案 8 :(得分:0)

纠正这个:

root_comment.html

{% extends 'students/base.html' %}
{% load i18n %}
{% load static from staticfiles %}

{% block content %}

<ul>
{% for comment in comments %}
    {% if not comment.parent %}                   ## add this ligic
    {% include "comment/tree_comment.html" %}
    {% endif %}
{% endfor %}
</ul>

{% endblock %}

tree_comment.html

<li>{{ comment.text }}
    {%if comment.children %}
        <ul>
         {% for ch in comment.children.get_queryset %}     # related_name in model
              {% with comment=ch template_name="comment/tree_comment.html" %}
                   {% include template_name %}
              {% endwith %}
         {% endfor %}
         </ul>
    {% endif %}
</li>

例如 - model:

from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _


# Create your models here.
class Comment(models.Model):
    class Meta(object):
        verbose_name = _('Comment')
        verbose_name_plural = _('Comments')

    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        parent_link=True,
        related_name='children',
        null=True,
        blank=True)

    text = models.TextField(
        max_length=2000,
        help_text=_('Please, your Comment'),
        verbose_name=_('Comment'),
        blank=True)

    public_date = models.DateTimeField(
        auto_now_add=True)

    correct_date = models.DateTimeField(
        auto_now=True)

    author = models.ForeignKey(User)

答案 9 :(得分:-2)

我有一个类似的问题,但是我首先使用JavaScript实现了解决方案,然后考虑了如何在django模板中完成相同的操作。

我使用序列化工具将模型中的列表转换为json,并使用json数据作为我的层次结构的基础。