Категории

Язык
Окружение
Проект
Циклы статей

24 сентября 2014 г. 12:53 (ред. 24 сентября 2014 г. 17:15)
Как и обещал, речь в статье пойдёт о приложении django-sitecats, о том, как его использует pythonz.net, а также о том, при чём тут кошки, и чем метки отличаются от категорий.
Для тех, кого прежде всего интересует проблема кошек в названии приложения, скажу сразу: кошки ни при чём, далее в статье речь пойдёт о категориях.

Появившееся недавно приложение django-sitecats, является попыткой взглянуть на проблему категоризации материалов на сайтах сбоку. И сейчас я попытаюсь объяснить, что имею в виду.

Беглый осмотр популярных пакетов для категоризации материалов на https://www.djangopackages.com обнаруживает интересную вещь: если оставить в стороне django-categories (который, не смотря на описание, вряд ли можно относить к общим решениям) и таксономические плагины для django-shop, можно решить, что систематизация на сайтах, использующих Django, реализуется при помощи меток. Такой подход, зачастую, является вполне приемлемым вариантом, когда плоские таксономии устраивают.

Однако людей считающих, что «плоские таксономии» это осксюморон, такое положение дел устроить, конечно, не может. На почве этого внутреннего конфликта и возникает пакет django-sitecats, позволяющий в терминах иерархий описывать более-менее приличные таксономии. При помощи этого приложения мы создаём иерархии категорий, к которым сможем привязывать объекты сайта, таким образом структурируя информацию.

Например, здесь, на pythonz.net, используется достаточно простая таксономия, описанная иерархией, состоящей всего из двух уровней — http://pythonz.net/categories (например: «Язык — русский», «Проект — Django»).

Характерной чертой приложения является обращение к категориям (если желаете, можете по-прежнему называть их тегами, которые метки) через их родителей. Так, например, чтобы иметь возможность работать с категориями «байткод», «генераторы», «конкурентность», «сборка мусора» нам достаточно обратиться к их родительской категории «Аспект языка». Обращение к родительским категориям из кода производится при помощи псевдонимов (alias).

Для наглядности, примерно так выводится список категорий, связанных с объектом на страницах с детальной информацией (см. http://pythonz.net/books/3 блок «Категории» в правой части страницы):


# Код из представления, собирающего страницу с детальной информаций о книге.
book = ... # Здесь у нас экземпляр модели Book.
# Модель Book мы унаследовали, кроме прочего, от sitecats.models.ModelWithCategory.
# Это наследование позволило нам упростить работу работу с категориями. См. ниже.

# Настраиваем параметры списков категорий.
# Например, если книга фигурирует в категориях «русский» и «Django»,
# будет сформировано два списка категорий: «Язык» и «Проект».
# 'show_title': True говорит, что мы хотим видеть на странице заголовки
# родительских категорий «Язык» и «Проект».
book.set_category_lists_init_kwargs({'show_title': True})

... # И в конце представление выводит страницу.

Вот практически и всё. Осталось в шаблонах, на места, где нужно вывести списки категорий, проставить тег {% sitecats_categories from book %} (здесь book содержит объект book, сформированный в коде выше).

Для изменения принадлежности объектов к категориям, можно включить редактор:

# Код из представления, собирающего страницу редактирования данных о книге.
from sitecats.toolbox import get_category_aliases_under

book = ... # Здесь у нас экземпляр модели Book.
book.enable_category_lists_editor(request,
# По умолчанию редактор выводит только списки для родителей тех
# категорий, которые уже связаны с объектом, в нашем случае: «Язык» и «Проект».
# Однако нам понадобилась возможность выбирать из всех родителей
# расположенных на корневом уровне иерархии, поэтому мы
# в additional_parents_aliases передаём псевдонимы всех корневых родителей.
# Псевдонимы получаем при помощи get_category_aliases_under().
additional_parents_aliases=get_category_aliases_under(),

# Устанавливаем параметры редактора.
# `allow_add` разрешает добавлять книгу в уже существующие категории;
# `allow_remove` разрешает удалять привязки книги к категориям;
# `allow_new` здесь позволяет суперпользователям создавать новые категории и привязывать к ним книгу.
editor_init_kwargs={'allow_add': True, 'allow_remove': True, 'allow_new': request.user.is_superuser}

# Настраиваем обработчик запросов от редактора категорий.
# Здесь мы задаём дополнительную метку для сообщений об ошибках,
# генерируемых обработчиком. Эта метка в нашем случае превратиться
# в имя css класса, используемого для стилизации сообщений об ошибках.
handler_init_kwargs={'error_messages_extra_tags': 'alert alert-danger'},

# Ну и здесь мы выведем названия родительских категорий.
lists_init_kwargs={'show_title': True},
)

# В шаблоне будем использовать всё тот же тег {% sitecats_categories from article %}`
# выводить редактор он тоже умеет.

Теперь попробуем вывести все категории, к которым отнесены объекты (как это сделано в разделе «Категории»). В этом нам поможет функция конструктор списков категорий get_category_lists()


# Код из представления, собирающего страницу со списком используемых категорий.
from sitecats.toolbox import get_category_lists, get_category_aliases_under
from django.core.urlresolvers import reverse


cat_lists = get_category_lists(
# Ограничиваем выборку родительскими категориями из корня иерархии.
additional_parents_aliases=get_category_aliases_under(),
init_kwargs={
# И тут будем показывать заголовки родителей.
'show_title': True,
# Теперь укажем, как формировать ссылки на страницы с детальной
# информацией по категории.
# Предположим, что у нас в urls.py уже определен URL с именем `category-details`,
# вот он и послужит нам.
'show_links': lambda cat: reverse('category-details', args=[cat.id])
})

# В шаблоне опять тег {% sitecats_categories from cat_lists %}`

Ну, а стилизовать списки категорий и их редакторы вы можете при помощи своих css стилей.

Вот такое приложение, если вкратце. Больше информации в исходном коде и документации.

На этом откланиваюсь. Пользуйтесь, участвуйте в разработке — https://github.com/idlesign/django-sitecats