如何在不使用django-mptt的情况下在django模板中实现树结构。
我有模特。
class Person(TimeStampedModel):
name = models.CharField(max_length=32)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
现在我想要..
Parent
Child 1
subchild 1.1
subchild 1.2
nextsubchild 1.2.1
Child 2
Child 3
应该点击名称以显示他们的个人资料。
答案 0 :(得分:11)
我刚刚完成了这个。我想要一个子导航的树结构,但我不想对递归模板做任何奇怪的事情。
我实现的解决方案非常简单:我只是简单地在视图中递归(在我的例子中是一个通用的辅助函数),并将层次结构展平为一个简单的列表。然后,在我的模板中,我只使用for循环迭代列表。
列表中的每个元素可以是以下三种内容之一:“in”,对象或“out”。在我的例子中,我在视图中构建了一系列ul li元素,所以当我遇到“in”时,我会创建一个新的ul,当我遇到“out”时,我会关闭ul。否则,我渲染项目。
我的模板代码如下所示:
{% for item in sub_nav %}
{% if item == "in" %}
<ul>
{% else %}
{% if item == "out" %}
</ul>
</li>
{% else %}
<li>
<a href='{{item.full_url}}'>{{item.name}}</a>
{% if item.leaf %}
</li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
辅助函数中的代码如下所示:
def get_category_nav(request,categories=None):
"""Recursively build a list of product categories. The resulting list is meant to be iterated over in a view"""
if categories==None:
#get the root categories
categories = ProductCategory.objects.filter(parent=None)
categories[0].active=True
else:
yield 'in'
for category in categories:
yield category
subcats = ProductCategory.objects.select_related().filter(parent=category)
if len(subcats):
category.leaf=False
for x in get_category_nav(request,subcats):
yield x
else:
category.leaf=True
yield 'out'
使用这些代码段,您应该能够构建任何类型的分层树,而无需在模板中进行任何递归,并将所有逻辑保留在视图中。
我知道已经有一个已接受的答案,但我想我会发布这项技术,以防它帮助其他人。
答案 1 :(得分:10)
来自Django while loop问题和
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
# view.py
@register.inclusion_tag('children.html')
def children_tag(person):
children = person.children.all()
return {'children': children}
# children.html
<ul>
{% for child in children %}
<li> <a href="{{ child.get_absolute_url }}">{{ child }}</a></li>
{% if child.children.count > 0 %}
{% children_list child %}
{% endif %}
{% endfor %}
</ul>
# your template
{% children_tag parent %}
答案 2 :(得分:3)
这些都是很好的答案,但我巩固了一点,并把它放在实际模型上。
class RecursiveThing(models.Model):
name = models.CharField(max_length=32)
parent = models.ForeignKey('self', related_name='children', blank=True, null=True)
def as_tree(self):
children = list(self.children.all())
branch = bool(children)
yield branch, self
for child in children:
for next in child.as_tree():
yield next
yield branch, None
然后在你的模板中:
<ul>
{% for thing in things %}
{% for branch, obj in thing.as_tree %}
{% if obj %}
<li>{{ obj.name }}
{% if branch %}
<ul>
{% else %}
</li>
{% endif %}
{% else %}
{% if branch %}
</ul>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
答案 3 :(得分:0)
这很简单
您在视图中所要做的就是获取所有对象:
people = Person.objects.all()
然后在你的模板中:
{% for person in people %}
<li>- {{person.name}} </li>
{% for child in person.children.all %}
<ul>* {{child.nom}} </ul>
{% endfor %}
</li>
{% endfor %}