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

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

问题描述

我有一个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 )中循环播放,我很容易用纯文本来表示树:

  def node(parent,level):
children = Tag.objects.filter(parent = parent)
for c in children:
spaces =
for i in xrange(0,level):
spaces + =
打印%s%s%(空格,c.name)
节点(c.pk,级别+ 1)

节点(无,0)

我不确定的是如何将整个树放入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()函数调用。但是像我说的那样,我不知道如何把它转变成一个单一的数据结构,传递给我的模板。



想法?我想我可能想要建立一种字典,我只是不能在这里跟随。

解决方案

正如Jproffitt所说, Django
MPTT
是一个很好的方式来实现你想要的



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

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

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



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



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

 #yourapp / tags_list.html 
< ul>
{%标签中的标签%}
< li> {{tag.name}}< / li>
{%if tag.children.exists%}
{%with tag.children.all as tags%}
{%includeyourapp / tags_list.html%}
{%endwith%}
{%endif%}
{%endfor%}
< / ul>

这样,模板只能自动调用自己,直到没有
更多的孩子标签。此解决方案需要您在标签模型中指定相关名称:

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

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


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)

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)

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}

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)

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.

解决方案

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.

Alternative solution without a third-party app

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")

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

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

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