django : отображение древовидных данных

Столкнулся с необходимостью вывести дерево элементов (список категорий с подкатегориями). Глубина вложенности изначально не ограниченна. Решение задачи дальше.

Древовидные данные

Итак, есть модель:

class Category(models.Model):
    master = models.ForeignKey('self',related_name='translations',null=True,blank=True)
    title = models.CharField(max_length=250)
    parent = models.ForeignKey('self',blank=True,null=True)
    description = models.TextField()
    cdate = models.DateTimeField(auto_now_add=True)
    mdate = models.DateTimeField(auto_now=True)
    language = models.CharField(max_length=2, choices=settings.LANGUAGES)
    def __unicode__(self):
        return self.title

Как видно, поле parent позволяет указать родителя и таким образом создать вложения неограниченной глубины.

Теперь возникает вопрос - как в шаблоне организовать рекурсивный вывод данных. Я пропущу все прелюдии и ошибочные пути, которыми я шел, такие как get_levels_count(), get_level_n(n) и т.п. В конечном итоге нужную функциональность удалось организовать при помощи шаблонных тегов.

Шаблонный тег для рекурсивного вывода данных

Начнем писать свой тег.

1. В папке своего приложения создаем папку templatetags, в ней создаем пустой файл __init__.py и файл category_tree.py. В последнем собственно и будет наш тег.

2. В файл category_tree.py вписываем следующее:

from django import template
from shop.products.models import Category

register = template.Library()

@register.inclusion_tag('products/templatetags/category_tree.html')
def category_tree(context,category):
    children = Category.objects.filter(parent=category)
    return {'category': category, 'children' : children,}

3. В шаблон products/templatetags/category_tree.html пишем следующее:

{% load category_tree %}
<li>{{ category.title }}
<ul>
    {% for child in children %}
	<li>{% category_tree child %}</li>
    {% endfor %}
</ul>
</li>

4. Ну и наконец, в главный шаблон, в котором нужно вывести дерево:

{% load category_tree %}
    <ul>
    {% for category in categories %}
	<li>{% category_tree category %}</li>
    {% endfor %}
    </ul>

Собственно, это все. Виват, django!

Запись опубликована в рубрике django с тэгами . Создать закладку наpermalink. Оставить комментарийили trackback:Trackback URL.

Один комментарий

  1. nik vasin
    Опубликован 10 апреля 2009 в 10:32 | Прямая ссылка

    Отлично!
    Есть такой проект satchmo. В нем этот вопрос решается через xml.etree. Ваше решение работает быстрее. И выглядит весьма элегантно.

один trackback

  1. [...] Original post by solshark [...]

Оставить комментарий

Ваш e-mail никогда не будет опубликован или передан третьим лицам.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>