Знакомство с django-admin поражает воображение. Непосредственно на основе моделей базы данных вы получаете готовый веб-интерфейс. Этот интерфейс будет иметь фильтры поиска, учитывать условия для полей, подключать справочники связанных объектов. Далее, просто добавляя «подсказки» для моделей базы, вы сможете сделать интерфейс еще удобнее с минимальными трудозатратами.
В общем, возникает вполне естественное желание использовать всю эту навороченную систему для того, чтобы построить пользовательский интерфейс (автоматизированное рабочее место).
Так я и поступил — и это оказался путь в капкан. Если хватит задора на серию статей, то дальше расскажу о том, как из него выбраться, прихватив с собой кусочек сыра :)
В начале все идет просто замечательно. Ну разве могут не радовать такие возможности:
booking/admin.py
from django.contrib import admin from booking.models import Sale class SaleAdmin(admin.ModelAdmin): ## Настройка табличного просмотра # поля для табличного просмотра list_display = ('docid', 'date', 'doctype', 'customer', 'amount', 'manager',) # поля для полнотекстового поиска search_fields = ('docid', 'customer',) # поля, актуальные значения которых будут # выведены в боковой колонке и позволят фильтровать список list_filter = ('doctype', 'manager',) # поля, недоступные для изменения # поле, по которому будет доступна навигация по иерархическому календарю date_hierarchy = 'date' ## Настройка формы редактирования # поля, защищенные от записи readonly_fields = ('inserted', 'inserted_by', 'id', 'manager',) # поля, которые не надо показывать exclude = ('something') # группировка полей по "строкам" формы для лучшего восприятия fieldsets = ( (None, { 'fields': ( ( 'agency', 'docid', 'doctype', ),( 'date', ),( ),( 'fare', 'comission', ),( 'amount', ),( 'comments', ),( 'manager', 'inserted', 'inserted_by', ),)}), ) # из этой формы будет позаимствован метод clean() form = SaleForm # дополнительный css class Media: css = { 'all': ("/media/css/admin_form.css",) } admin.site.register(Sale, SaleAdmin)
Описываем, наслаждаемся. Фильтры, интерактивные календарики, дропдаун и красивая зеленая кнопочка «+», дающая возможность на ходу зарегистрировать продажу…
Получается примерно так (при том, что мы не написали ни строки кода для дизайна, отображения, сохранения и проверки полей, а все работает — ну разве не лапочка?):
И вы «бесплатно» получите не только эту форму, но и табличный просмотр с указанными фильтрами, соответственно.
Вот только даты в табличном просмотре почему-то выводятся как «15 Март 2012», а не ‘15.03.2012’, ну это мы сейчас поправим… так, документация…, google…, vi /usr/lib/pymodules/python2.5/django/contrib/admin/…, google… упс!
При включенной locale формат даты задан жестко только ей и ни на какие настройки не реагирует.
Есть workaround:
from django.utils.translation import ugettext as _ class SaleAdmin(admin.ModelAdmin): ... list_display = (...,'format_date',...) def format_date(self, obj): return obj.date.strftime('%d.%m.%Y') format_date.short_description = _("Date") format_date.admin_order_field = 'date'
Ну… выкрутились. Особенно приятно, когда у вас не одна, а три даты в списке ;)
Поздравляем себя с маленькой победой и идем показывать клиенту.
Клиент добрый и изо всех сил делает вид, что понимает, что смотрит на черновой вариант… вот только как бы разделить разряды в колонке суммы?
Конечно! Мы же уже умеем это решать! Уходим и делаем знакомым манером. По ходу понимаем, что, «к клиенту не ходи» — а цифирки надо бы еще выровнять вправо… так, документация…, google…, vi /usr/lib/pymodules/python2.5/django/contrib/admin/…, google… упс!
Не выправить.
С числами вообще мало что можно выправить, поскольку их обработка вшита в код django-admin.
А подбивать итог?
О! Нашли django-reporting! (ему будет посвящена отдельная заметка).
Только вот беда… из него можно попасть в редактирование записи, а обратно выход — в стандартный change-list.
А как бы нам теперь сделать отрицательные числа красненькими?
А как бы нам тут же рисовать остаток по счету?
А как бы нам вставить свои ссылочки туда, где «Добро пожаловать» и «Выход»?
А как бы нам сделать русскими названия модулей на главной странице?
А как нам быть с тем, что клиент вообще не понимает, чего ему делать, глядя на главную страницу, в том дизайне, который у нее автогенерится по-умолчанию?
Наверное, на некоторые из этих вопросов есть более-менее годные ответы, некоторые решаются правкой дефолтных шаблонов (скопированных в свой /templates/admin).
Но, в итоге, получается довольно дурацкая ситуация: программист, начинающий использовать Django с неизбежностью познакомится с django-admin и захочет использовать его для построения интерфейса. И, в результате…
- Либо он добьется результата затратив не меньше усилий, чем на написание собственного интерфейса (потому что Django и без django-admin неплох). В результате он обречет себя на постоянное преодоление условностей django-admin и сильно ограничит свои возможности делать «произвольный» интерфейс по мере необходимости.
- Либо он потеряет время на то, чтобы понять бесперспективность этого подхода и будет искать иной каркас приложения или создавать свой.
Я пошел по второму пути, но по дороге прихватил некоторые «вкусности» django-admin, такие как базовый шаблон, форму редактирования (change_form) с разбивкой по полям на основе adminform и табличный список (change_list) с группировкой и подитогами на основе django-reporting. Большинство этих компонентов претерпели некоторые изменения и в результате получился довольно забавный велосипед.
О том, как собрать такой же и как поехать на нем, я расскажу в следующих статьях этого цикла.
Мои выводы
- django-admin нужно осваивать и использовать. Он позволяет действительно быстро делать те вещи, которые нужны только вам и позволит сэкономить массу времени.
- Использовать django-admin для создания пользовательского интерфейса — тупиковый путь.
- Самое печальное в том, что преодоление трудностей на этом пути не сделает счастливым вашего клиента — потому что результатом будет все равно технически-ориентированный интерфейс, как это удобно программисту, а не проблемно-ориентированный интерфейс, которого ожидает клиент.
P.S.
Статья год пролежала на полке. Вышел новый Django, может чего и изменилось к лучшему.