在Django temp中表示对象树

2024-04-25 20:08:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Django模型,它有一个指向同一类的ForeignKey,有效地创建了一个树:

class Tag(models.Model):
    name = models.CharField(max_length=50)
    parent = models.ForeignKey('self', blank=True, null=True)

在Django shell(./manage.py shell)中,我可以很容易地将树表示为纯文本:

^{pr2}$

我不确定的是如何将整个树放入Django模板中。我创建了一个自定义的模板标记来简化这一点,但是我不知道如何将数据传递给模板,以便轻松地在树上迭代以在模板中显示。下面是基本模板标记。在

@register.inclusion_tag("core/tags.html")
def render_tags(**kwargs):
    tags = Tag.objects.all()
    return {"tags":tags}

我知道以上是非常基本的,我只是不知道从这里到哪里去。我想如果Tag类有一个函数来获取它的子类,可能会更容易,所以我在这个类上也有:

    def children(self):
        return Tag.objects.filter(parent=self.pk)

我在那里使用self.pk,那么树的根就是rootTag=Tag(),因为它没有保存,所以它没有pk,rootTag.children()将找到没有父标记的任何标记,然后这些标记中的任何一个都可以继续调用它们的children()函数。但正如我所说的,我不知道如何将其转换为某种类型的单一数据结构以传递给我的模板。在

有什么想法?我想我可能想建立一种口述,我只是不能坚持到底。在


Tags: django标记self模板trueobjectsmodelsdef
2条回答

我搜索得越多,我就越意识到尝试用模板递归来实现这一点并不是可行的,但我还是希望暂时避免使用django mptt,因为对于我认为是一个简单问题来说,它似乎太多了,而且我不打算拥有非常大的树。在

An answerthis related question注意到实际上不应该使用模板递归,而是在视图中处理序列化。我原以为这会更好,正如我在最初的问题中提到的,假设我需要构建一个dict。在

This answer基本上就是我要找的。serializable_object是我可以传递到模板中的东西,如果我决定以后使用json,那么很容易做到,正如答案中所述。在

我将选择Eliot的答案作为正确答案,因为django mptt可能是这里要做的“最正确”的事情,但是对于任何想要避免另一个第三方应用程序的人来说,这是一个替代方案。在

class Tag(models.Model):
    name = models.CharField(max_length=50)
    description = models.CharField(max_length=100, blank=True)
    parent = models.ForeignKey('self', blank=True, null=True)

    # Not necessary, can use Tag.tag_set.all()
    # But this function uses pk which allows
    #    rootTag=Tag() 
    #    rootTag.children()
    # Because rootTag has no pk
    def children(self):
        return Tag.objects.filter(parent=self.pk)

    def serializable_object(self):
        obj = {'name': self.name, 'children': []}
        for child in self.children():
            obj['children'].append(child.serializable_object())
        return obj

使用该模型,您可以:

^{pr2}$

或者:

tags = []
for t in Tag.objects.filter(parent=None):
    tags.append(t.serializable_object())

# And if you need JSON, 
from django.utils import simplejson
simplejson.dumps(tags)

正如jproffit提到的,Django MPTT是一种很好的方法来实现什么 你想要的。在

使用它,您可以递归地访问模板中的子实例, 像这样:

{% load mptt_tags %}
<h1>Tags</h1>
<ul>
{% recursetree tags %}
    <li>{{ node.name }}
        {% if not node.is_leaf_node %}
            <ul>
                {{ children }}
            </ul>
        {% endif %}
    </li>
{% endrecursetree %}
</ul>

我有一个项目,它很容易设置和使用。在

无第三方应用程序的替代解决方案

如果你不想使用一个专用的应用程序,我认为这些解决方案可能会奏效 (未测试):

^{pr2}$

这样,模板应该递归地调用自己,直到没有 更多子标签。您需要在模型中指定一个相关的名称:

parent = models.ForeignKey('self', blank=True, null=True, related_name="children")

但是,请小心,这些解决方案将涉及比使用MPTT更多的数据库查询。在

相关问题 更多 >