问题描述
我有一个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所说,是一个很好的方式来实现你想要的
。
使用它,您可以在模板中递归地访问子实例,
就像这样:
{%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 DjangoMPTT is a nice way to achieve whatyou 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 nomore 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模板中表示一个对象树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!