我有类别的树结构。具有引用自身的外键的类别。
class Category(MetaData):
parent = models.ForeignKey('self', blank=True, null=True, verbose_name='parent category', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
description = models.TextField()
因为我不知道类别树的深度(不能用于),我需要使用递归函数:
def cat_for_parents(self, cat_obj):
...
if cat_obj.parent_id:
p = cat_obj.parent
...
self.cat_for_parents(p)
但是我如何在模板中实现这个函数来获得这样的东西(理论上无限递归循环):
<ul>
<li>CategoryA
<ul>
<li>SubCategA1
<ul>
<li> Subcateg Subcateg B1
<ul>
<li> Subcateg SubCateg C1>
<li> Subcateg SubCateg C2>
<ul>
<li> Subcateg Subcateg B2>
.............
答案 0 :(得分:1)
我用inclusion_tag
解决了这个问题。
示例:
model
:
#just add related_name:
parent = models.ForeignKey('self', blank=True, null=True, related_name='subs', on_delete=models.CASCADE)
views.py
:
categories = Category.objects.filter(parent=None)
# then pass it to template
template
:
<ul>
{% for category in categories %}
<li>
{{ category.name }}
{% if category.parent.count > 0 %}
{% tree_structure category %}
{% endif %}
</li>
{% endfor %}
</ul>
自定义标记功能:
@register.inclusion_tag('path/to/tree_structure.html')
def tree_structure(category):
subs = category.subs.all()
return {"subs": subs}
tree_structure.html
:
# remember to load your custom tags file
<ul>
{% for sub in subs %}
<li>
{{ sub.name }}
{% if sub.parent.count > 0 %}
{% tree_structure sub %}
{% endif %}
</li>
{% endfor %}
</ul>
工作原理:
获取没有任何父级的类别并将其发送到模板。 在模板中,我们使用for循环逐个呈现类别,然后在转到下一个类别进行渲染之前,检查该类别是否具有任何subs。 如果该类别有任何子类,您将把类别传递给自定义模板标记,然后您将获得该给定类别的所有子类别,并将其传递给另一个模板文件以呈现它们,但在完成之前,请检查该类别类别,以查看是否有一个子类别,如果它只是在你完成渲染第一个之前再次调用自定义函数。它将持续到没有更多的类别和子类别,并在最后传递一个完整的模板,其中包含第一个传递的类别的所有子类别到主模板,以便在其他类别之前呈现。
我自己无法测试此代码,因此可能存在小问题。
另请查看自定义模板标记的文档: Custom template tags and filters