在 Django 模板中表示对象树 [英] Represent a tree of objects in Django template

查看:26
本文介绍了在 Django 模板中表示对象树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Django 模型,它有一个同一个类的外键,有效地制作了一棵树:

I have a Django model which has a ForeignKey to the same class, effectively making a tree:

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

在 Django shell (./manage.py shell) 中使用递归,我可以轻松地将树表示为纯文本:

Playing around with a recursive in the Django shell (./manage.py shell), I am easily able to represent the tree as plain text:

def nodes(parent, level):
    children = Tag.objects.filter(parent=parent)
    for c in children:
        spaces = ""
        for i in xrange(0,level):
            spaces+="  "
        print "%s%s" % (spaces,c.name)
        nodes(c.pk,level+1)

nodes(None,0)

我不确定的是如何将整个树放入 Django 模板中.我创建了一个自定义模板标记来简化此操作,但我不知道如何将数据传递给模板以轻松遍历树以在模板中显示.这是基本的模板标签.

What I am unsure of is how to get the entire tree into a Django template. I've created a custom template tag to make this easier, but I can't figure out how to pass the data to the template to easily iterate over the tree for display in a template. Here's the basic template tag.

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

我知道以上内容非常基本,我只是不知道从哪里开始.我认为如果 Tag 类有一个函数来获取它的子类可能会更容易,所以我也有这个类:

I know the above is very basic, I just am not sure where to go from here. I thought it might be easier if the Tag class had a function to get its children, so I also have on the class:

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

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

I use self.pk there, then the root of the tree is simply rootTag=Tag(), since it has no pk since it is not saved, rootTag.children() will find any Tags which do not have a parent Tag, and any of these tags can then just continue to have their children() function called. But like I said, I do not know how to turn this into a single data structure of some sort to pass to my template.

想法?我想我可能想建立一种字典,我只是无法在这里跟进.

Thoughts? I think I probably want to build a kind of dict, I'm just not able to follow through here.

推荐答案

正如 Jprofitt 提到的 DjangoMPTT 是实现目标的好方法你要.

As Jproffitt mentionned it Django MPTT is a nice way to achieve what you want.

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

Using it, you can then access children instance, recursively, in your template, like this:

{% 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>

我的一个项目使用了它,它易于设置和使用.

I have it for one of my projects and it's easy to set up and to use.

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

If you don't want to use a dedicated app, I think these solution might work (untested):

# yourapp/tags_list.html
<ul>
{% for tag in tags %}
    <li>{{ tag.name }}</li>
    {% if tag.children.exists %}
       {% with tag.children.all as tags %}
            {% include "yourapp/tags_list.html" %}
        {% endwith %}    
    {% endif %}
{% endfor %}
</ul>

这样,模板就应该递归调用自己,直到没有更多儿童标签.此解决方案需要您在标签模型中指定相关名称:

This way, the template should just call himself recursively until there is no more children tags. This solution needs that you specify a related name in your Tag model :

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

但是,请注意,与使用 MPTT 相比,这些解决方案将涉及更多的数据库查询.

However, be careful, these solution will involve more database queries than using MPTT.

这篇关于在 Django 模板中表示对象树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆