Опять говорю "Ура!". В предыдущий раз это это было в связи с апгрейдом ORM. На это раз кардинальным улучшениям подверглась ещё одна очень важная часть Django - автоматический CRUD, она же в официальной терминологии - админка. После достаточно продолжительного этапа разработки и тестирования NFA бранч влился в транк и подарил пользователям джанги кучу новых ощущений: от радости за сей факт, до тревоги по поводу необходимости переписывать имеющийся код. Но нас, любителей самых "свежих срезов", это никогда не останавливало.:)
Многие уже успели изменить транку с NFA брачем и некоторое время погонять новую админку в своих проектах. Но не все такие смелые:)
Вообще это очень интересный процесс когда ты видишь по увеличившемуся числу changeset'ов перед релизом чего-то нового, что вот оно скоро свершится. Так было с Малкольмом, когда он допиливал рефакторинг ORM и произошло сейчас, благо спринт организовали. На этот раз главная звезда Брайен Роснер. Эти приятные хлопоты по полировке деталей, правки уже кажущихся не очень существенными сообщениями об ошибках, именования переменных и функций, и т.п. - как часть неотъемлемая часть.
Так что же мы получили? Во первых случился важнейший переворот в принципе описания админки. Если раньше её описание было частью определения модели, то теперь оно происходит отдельно. Что, наконец, дает возможность кастомизировать админку для моделей сторонних приложений без всяких хаков и редактирования чужого кода.
Помимо этого, возможности для кастомизации админки как таковой значительно расширились. Теперь более тонко можно настраивать её отображение и функционал.
И конечно же, сам факт появления адмника на новых формах в транке, приближает нас к долгожданному релизу версии 1.0 джанги. Который, если всё сложится как надо случиться уже в начале осени.
А теперь пройдемся по нововведениям и попытаемся сообразить, где нам это пригодится.
Настраиваем админку по новому
Для начала придумаем вот такую простую модель:
class Article( models.Model ):
title = models.CharField( max_length = 250 )
author = models.ForeignKey( User )
date = models.DateTimeField( default = datetime.now )
text = models.TextField()
Далее создадим класс описания админки для нашей модели. Кстати, нам рекомендуется, код админки хранить в файле admin.py, который автоматически импортируется в нужный момент.
from django.contrib import admin
class ArticleAdmin(admin.ModelAdmin):
pass
admin.site.register(Article, ArticleAdmin)
В последней строке происходит регистрация данного описания админки и модели. Но это мы сделали дефолтную админку, теперь мы её будем кастомизировать.
class ArticleAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('title', 'text', )
}),
('Meta', {
'classes': ('collapse',),
'fields': ('author', 'date', )
}),
)
Как видно, изменилось название атрибута отвечающего за группировку полей при отображении формы редактирования. Раньше это были fields, теперь же это более логичные fieldsets. В остальном формат описания не изменился.
Ещё не плохо было бы избавиться от селект бокса, который отвечает а выбор автора. Благо теперь есть возможность превратить его в радио селект.
radio_fields = { "author" : admin.HORIZONTAL }
Аналогично можно сделать его и VERTICAL. Такую кастомизацию можно делать либо для ForeignKey полей, либо для тех у которых есть choices.
Конечно же сохранились и привычные list_display, search_fields, list_display_links, list_filter и т.д.
Теперь очень важное нововведение. Все мы помним, что edit_inline функциональность была реализована не очень хорошо в старых формах. И имела очень ограниченные возможности по настройке поведения. По сути можно было менять только кол-во отображаемых редактируемых элементов. Теперь же мы можем достаточно тонко настроить редактируемые инлайн объекты.
Но для того чтобы понять как это теперь работает придется немного отвлечься от самой админки и переключиться на ещё одно нововведения, которое мы получили благодаря мерджу.
Формсеты
Формсет - это абстракция, позволяющая обрабатывать несколько однородных форм за раз (т.е. на одной странице). Поэтому они и родились в ходе работы над новой админкой, а точнее для редактируемых инлайн объектов.
Давайте же вместе разберемся что это и с чем его едят. Представим, что у нас форма для добавления некой записи
class EntryForm( froms.Form ):
name = forms.CharField()
info = forms.TextField()
И для облегчения и убыстрения процесса мы захотели, чтобы можно было сразу несколько записей добавлять за раз. Тут на формсет и пригодится. Кстати, newforms стали теперь просто forms. Немного грустно, но так лучше:)
from django.forms.formsets import formset_factory
EntryFormset = formset_factory( EntryForm, extra = 3 )
formset = EntryFormset()
Вот таким не хитрым способом создается формсет из трех форм для добавления 3х записей. За количество клонов отвечает параметр extra.
Работать с ним достаточно просто. Для того чтобы пробежаться по всем формам набора надо:
for form in formset.forms:
form.as_p()
Аналогично и в шаблоне.
Для обработки форм используется обобщенный механизм всего формсета, идентичный обычным формам:
if request.POST:
formset = EntryFormset( request.POST )
if formset.is_valid():
#обрабатываем данные каждой из форм
else:
formset = EntryFormset()
Также можно предоставлять начальные данные, добавлять поля и дополнительные валидаторы. Обо всем об этом можно прочитать в документации
Но и тут не обошлось без применения DRY принципа и формсет можно построить прям из модели примерно так:
from django.forms.models import modelformset_factory
EntryFormset = modelformset_factory( Entry )
И как обычно в документации всё подробно расписано.
Вообще это вполне предсказуемо, что наравне с админкой улучшениям подвергся и сам newforms функционал.
Edit inline по новому
Вернемся к админке и настройке edit inline объектов. Путь для каждой нашей статьи будет присутствовать некоторые количество вспомогательных ссылок на какие-то полезные ресурсы. Модель для них будет такой:
class Link( models.Model ):
article = models.ForeignKey( Article )
name = models.CharField( max_length = 100 )
url = models.URLField()
Ну и конечно не плохо чтобы сразу на странице добавления статьи мы могли бы и полезные ссылки к ней добавить. Тут то нам и пригодится ещё один новый мета-атрибут админки:
inlines = [ LinkInlineAdmin ]
Где LinkInlineAdmin это класс описатель для внедряемых форм добавления ссылок. Он описывается так:
class LinkInlineAdmin( InlineModelAdmin ):
model = Link
Также как атрибут можно установить свой собственный formset или только форму - form, ну ещё кое-какие параметры.
Благодаря им, можно очень гибко настроить способ редактирования инлайн объектов.
Урлы для админки по новому
Теперь осталось правильно в urls.py указать на админку. Тут тоже всё по новому. Поскольку мы зарегистрировали мета-модель в глобально админке site, которая лежит в недрах contrib.admin, то маппинг должен выглядеть примерно так:
from django.conf.urls.defaults import *
from django.contrib import admin
urlpatterns = patterns('',
('^admin/(.*)', admin.site.root),
)
И тут мы получаем ещё один гибкий механизм, который нам позволяет иметь несколько админок. site это объект класса AdminSite, который мы можем создать сами и регистрировать "модельные" админки в нем. Соответственно и в urls.py ссылаться на них.
Вот собственно и всё.
Ещё, наконец, мы получили несколько generic views, который переведены на newforms. Это как приятное дополнение к обновленной адмике:)
Подробное описание возможностей админки вы можете найти в достаточно подробной документации. Ну и конечно иногда полезно заглянуть в код для полного прояснения нюансов.
Удачи нам и реализации самых смелых идей с админкой на новых формах!:)
Комментарии 14
Огромное спасибо за обзор! будем изучать
Оставлен 19 Июль 2008 в 08:42 ¶Интересно а alias newforms останется в грядущих апдейтах? Много проектов поэтому как то боязно апдейтить транк :-) P.S pycaptcha - страшная :-)
Оставлен 19 Июль 2008 в 17:51 ¶наверно ещё admin.autodiscover() забыл в urls.py ;)
Оставлен 20 Июль 2008 в 21:21 ¶Спасибо за статью!
Было бы намного нагляднее показать скриншоты админки например для Edit inline, опций admin.HORIZONTAL и т.д. В принципе представить можно, но "одна картинка стоит тысячи слов"...
Оставлен 21 Июль 2008 в 13:06 ¶Ага. Его в дефолтный шаблон проекта уже включили.
Оставлен 21 Июль 2008 в 15:26 ¶Так практически также как и раньше выглядит, только чуть-чуть добавили функционала в виде "чекбокса удаления".
Оставлен 21 Июль 2008 в 15:27 ¶Нет.
Ну на самом деле и контекстной заменой можно быстро решить.
Абсолютно согласен. Скорое её убью:)
Оставлен 21 Июль 2008 в 15:29 ¶Меня очень раздражало это new/old - я вчера сел и во всех проектах заменил - в Eclipse довольно все быстро это делается и никаких боков не наблюдается
ЗЫ: 2 Александр - что-то предпросмотр комментария не работает (пустое облачко отображается)
Оставлен 22 Июль 2008 в 11:50 ¶Обновил версию django. Первый раз почуствовал прелести не релизоности django.
Во первых
Это перестало работать (r'^admin/', include('django.contrib.admin.urls')), конечно теперь есть более красивое вроде бы Но не более логичное ('^myadmin/(.*)', admin.site.root),
Все бы ничего. (Особенно inline)
Только исчезло управление юзерами и их правами. Как вернуть???
P.S.В доке не нашел.
Оставлен 23 Июль 2008 в 18:45 ¶Fox, читайте документацию по новой админке. Там всё описано.
Если используете последний срез джанги, то не забывайте перед
Оставлен 23 Июль 2008 в 19:22 ¶svn upпроверять страницу несовместимых изменений. Тогда неожиданностей не будет.date = models.DateTimeField( default = datetime.now )
но perhaps, it's right :-))
date = models.DateTimeField( default = datetime.datetime.now() )
ошибочка понимаешь в коде будет.
admin.site.register(Article, ArticleAdminn)
it is too mistake because double nn
Спасибо
Оставлен 14 Август 2008 в 00:12 ¶Здравствуйте!!!
Цитата из поста
А где это написано что admin.py использовать надо и как это автоматически импортируется то есть что не нужно прописывать его нигде ?
Заранее спасибо за ответ
Оставлен 14 Август 2008 в 00:21 ¶Почему?
опечатка
Оставлен 14 Август 2008 в 11:59 ¶Так вот тут. В стандартно-сгенерированном urls.py будет
Оставлен 14 Август 2008 в 12:05 ¶admin.autodiscover()Комментирование данного поста закрыто.