Я только что закончил реализацию этого. Мне нужна древовидная структура для суб-навигации, но я не хотел делать ничего странного с рекурсивными шаблонами.
Решение, которое я реализовал, очень просто: я просто повторяю в представлении (в моем случае универсальную вспомогательную функцию) и сглаживаю иерархическую структуру в простой список. Затем в моем шаблоне я просто использую цикл 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'
Используя эти фрагменты, вы сможете построить любое иерархическое дерево, которое захотите, без каких-либо рекурсий в шаблоне и сохраняя всю логику в представлении.
Я знаю, что уже был принят ответ на этот вопрос, но я подумал, что опубликую технику на случай, если она кому-нибудь поможет.