Сегодня Django снова порадовала, мне требовалось отобразить список категорий с под категориями
не важно можно с ul-li.
мне надо было завернуть всё это в красивый селект, ну вот что-то вроде этого.

в хтмл это примерно вот так
<SELECT NAME=browser>
<OPTGROUP LABEL="Firefox">
<OPTION LABEL="2.0 or higher">
Firefox 2.0 or higher
</OPTION>
<OPTION LABEL="1.5.x">Firefox 1.5.x</OPTION>
<OPTION LABEL="1.0.x">Firefox 1.0.x</OPTION>
</OPTGROUP>
</select>Code language: HTML, XML (xml)
Допустим у меня есть 2 вот таких модели в вакууме.
Одна: категория — Firefox (как в примере выше.)
class Category(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.nameCode language: Python (python)
И вторая не посредственно список, где есть поле указывающее на связь с родителем
class SubCategory(models.Model):
category_name = models.ForeignKey(Category)
name = models.CharField(max_length=200)
def __unicode__(self):
return self.nameCode language: Python (python)
Едем дальше.
в PHP, я бы в цикле прорисовки категорий поставил бы ещё один цикл выбирающий всех детей для данной категории. (хаха — много запросов ну и ладно)
Но тут у нас всё интереснее, в притом намного.
Мы во views должны сформировать что-то и отправить в шаблон уже как-то почти готовое для отображения.
Хочется городить велосипед, но тут Документация Django какбэ подсказывает
что есть такая хреновая, которая мне поможет.
Суть её в том, что тот массив что придёт к нам она может пересортироватьперегруппировать по любому полю, и поможет нам красиво его отобразить.
В итоге во views.py я делаю выборку того, что мне нужно.
Например вот так:
sub_category_list = SubCategory.objects.all()Code language: Python (python)
И всё вот это мы отправляем тихо мирно в шаблон.
А в шаблоне нас встретит уже магический regroup
Вот с такой конструкцией
{% regroup sub_category_list by category_name as categ_list %}
<select id="id_sub">
<option value="">-----</option>
{% for ca in categ_list %}
<optgroup label="{{ca.grouper}}">
{% for item in ca.list %}
<option value="{{ item.id }}"> {{ item.name }}</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>Code language: Python (python)
Теперь по порядку.
{% regroup sub_category_list by category_name as categ_list %}Code language: Python (python)
Группируем sub_category_list по полю category_name и называем результат categ_list
Дальше создаём html элемент, тут я думаю всё понятно.
и начинаем разбирать то, что у нас в categ_list
{% for ca in categ_list %}Code language: Python (python)
Тут рассказывать ничего не надо, перебираем элементы по порядку
<optgroup label="{{ca.grouper}}">Code language: Python (python)
Тут мы выводим то почему мы группировали {{ca.grouper}}
{% for item in ca.list %}Code language: Python (python)
Вложенный цикл, обходим то, что внутри группы (тут нам помогает ca.list )
<option value="{{ item.id }}"> {{ item.name }}</option>Code language: Python (python)
Собственно выводим всю эту красоту в конечный элемент
{% endfor %}
</optgroup>
{% endfor %}Code language: Python (python)
Вот и завершили все наши дела.
и получили нечто похожее на селект рутреккера тот, что в самом верху.
просто красиво и со вкусом.
