Изменения, которые мы сделали ранее — null=True, blank=True и verbose_name — являются изменениями на уровне модели, а не на уровне интерфейса администратора. То есть, эти изменения являются фундаментальной частью модели, интерфейс администратора Django просто использует их, и в них ничего специфического для административного интерфейса нет.
Помимо этого, интерфейс администратора предоставляет множество
возможностей настроить его работу для конкретной модели. Эти
настройки реализуются с помощью классов
ModelAdmin.
Давайте погрузимся в настройку интерфейса, определив поля,
которые будут отображатся в списке редактирования для нашей
модели Author. По умолчанию, в списке
изменения отображается результат выполнения метода
__unicode__() для каждого объекта модели. В
главе «Модели» мы определили
метод __unicode__() для модели
Author так, чтобы он возвращал имя и
фамилию:
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, verbose_name='e-mail')
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
В результате список изменения обьектов
Author отображает имя и фамилию вместе,
вы можете это увидеть на рисунке «Страница списка редактирования авторов»:
Мы можем изменить это стандартное поведение, добавив в список дополнительные поля. Было бы удобно, например, если бы на этой странице отображался адрес электронной почты автора и можно было сортировать по имени и фамилии.
Чтобы это реализовать определим класс
ModelAdmin для модели
Author. Этот класс является ключом к настройке интерфейса администратора и самое простое, что он может — это определить список полей, которые будут
отображаться на странице списка редактирования. Приведём
admin.py к следующему виду:
from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book)
Вот, что мы сделали:
Мы создали класс
AuthorAdmin. Этот класс, унаследованый от django.contrib.admin.ModelAdmin, содержит настройки для конкретной модели в интерфейсе администратора. Мы изменили только одну настройку — list_display, назначив ей кортеж с именами полей, которые будут отображаться на странице списка редактирования. Естественно, модель должна содержать перечисленные поля.Мы изменили вызов admin.site.register(), добавив
AuthorAdminпослеAuthor. Это можно прочитать как: «Зарегистрировать модельAuthorс настройкамиAuthorAdmin».Функция
admin.site.register()принимает унаследованый отModelAdminкласс, как необязательный аргумент. Если вы не указали второй аргумент(как в случае сBookиPublisher), Django будет использовать настройки по умолчанию для этой модели.
Внеся новые настройки, обновляем страницу списка редактирования авторов, и вы увидите, что на странице теперь отображается три колонки — имя, фамилия и email-адресс. К тому же, можно производить сортировку по колонкам с помощью нажатия на их заголовок. (См. рисунок «Страница списка редактирования авторов с опцией list_display»):
Теперь добавим простую панель поиска. Добавьте
search_fields в
AuthorAdmin, вот так:
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
search_fields = ('first_name', 'last_name')
Обновите страницу и вы увидите панель поиска
вверху. (См. рисунок «Страница списка редактирования авторов с опцией search_fields».) Мы просто указали
странице со списком редактирования, чтобы она отобразила
панель поиска, которая производит поиск по полям
first_name и
last_name. Как можно ожидать, поиск
регистронезависимый и работает с обоими полями. То есть при
поиске строки «bar», будет найдет
как автор с именем Barney, так и автор с фамилией Hobarson.
Теперь добавим фильтр по дате к странице списка редактирования
модели Book:
from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
search_fields = ('first_name', 'last_name')
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book, BookAdmin)
Так как мы работаем с другим набором настроек, мы создали
отдельный класс ModelAdmin —
BookAdmin. Сначала мы определили
list_display для более приемлемого
отображения списка редактирования. Затем установили
list_filter, указав кортеж полей для
фильтра, который отобразится в правой части страницы. Для поля
даты, Django предоставляет готовые варианты фильтрации списка:
«Сегодня», «Последние 7 дней»,
«Этот месяц», «Этот год» —
разработчики Django нашли их самыми популярными вариантами
условий фильтрации. Рисунок «Страница списка редактирования книг с опцией list_filter» показывает, как это
выглядит:
Параметр list_filter работает с полями
разных типов, не только
DateField. (Попробуйте, например, с
полями BooleanField и
ForeignKey.) Фильтры отображаются, если
есть хотя бы два значения для фильтрации.
Ещё одним способом фильтрации по дате является использование
опции date_hierarchy:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
К странице списка редактирования сверху добавляется развернутая панель навигации по дате, как показано на рисунке «Страница списка редактирования книг с опцией date_hierarchy». Она начинается со списка доступных годов, затем месяцев и дней.
Обратите внимание, опция date_hierarchy в
качестве параметра принимает строку, а не
кортеж, потому что только одно поле даты может быть
использовано для иерархии.
Теперь изменим сортировку по умолчанию, чтобы на странице
списка редактирования, книги сортировались по дате публикации
в направлении убывания. По умолчанию, объекты сортируются в
соответствии с атрибутом ordering класса
Meta (См. главу «Модели»), но если
ordering там не указан, то сортировка не
определена.
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
Опция ordering административного интерфейса
работает так же, как и для класса Meta,
за исключением того, что использует только первое поле
указанное в списке. Чтобы указать тип сортировки по-убыванию,
необходимо поставить минус перед названием поля.
Обновим страницу списка редактирования. Обратите внимание, что возле заголовка поля даты публикации появилась стрелка, указывающая на направление сортировки. (См. рисунок «Страница списка редактирования книг с сортировкой».)
Мы рассмотрели основные настройки. Используя их, можно создать функциональный и удобный интерфейс администратора всего парой строк кода.
Так же, как и со списками редактирования, форма редактирования может быть настроена множеством способов.
Сначала определим порядок отображения полей. По умолчанию,
поля отображаются в том же порядке, в каком они были
определены в модели. Мы можем изменить этот порядок с помощью
опции fields в нашем классе, унаследованом
от ModelAdmin:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher', 'publication_date')
Теперь форма редактирования для книг будет использовать указаный порядок полей. Более естественно, если название книги будет идти перед автором. Конечно, порядок полей зависит от вашего способа работы с данными. Все формы разные.
Другой полезной особенностью, которую предоставляет опция fields является исключение определённых полей из списка редактирования. Просто уберите из списка поля, которые требуется исключить. Вы можете использовать это в случае, когда вашим административным пользователям позволено редактировать только определённые части данных или если часть полей изменяется с помощью внешнего автоматизированного процесса. Например, в нашей базе с книгами, мы можем спрятать поле publication_date:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher')
В результате, форма редактирования книг не предоставляет возможности изменения даты публикации. Это может быть полезно в случае, если вы издатель, которые предпочитает, чтобы его авторы не отодвигали даты публикаций. (Естественно, это чисто гипотетический пример.)
Когда пользователь использует эту неполную форму для добавления книги, Django устанавливает publication_date в None — поэтому убедитесь, что поле имеет свойство null=True.
Другая часто используемая настройка формы редактирования
используется для полей типа многие-ко-многим. Как можно было
увидеть на форме редактирования для книг, интерфейс
администратора представляет каждое поле типа
ManyToManyField в виде списка с возможностью выбора нескольких элементов, который является самым логичным методом отображения в формате HTML — но
такие списки не всегда удобно использовать. Если вам требуется
отметить несколько элементов, вы должны удерживать клавишу
Ctrl для этого. Интерфейс администратора
добавляет текст, который напоминает об этом, но представьте
ситуацию когда надо выделить сотню элементов.
Интерфейс администратора предоставляет решение —
filter_horizontal. Добавим его в
BookAdmin и посмотрим что получилось:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
filter_horizontal = ('authors',)
(Обратите внимание, что мы удалили параметр fields.)
Обновите страницу и вы заметите, что поле «Автор» теперь использует удобный javascript-интерфейс фильтрации, который позволяет искать среди элементов и перемещать выбранных авторов в поле выбранных и наоборот.
Мы настоятельно рекомендуем использовать
filter_horizontal для полей
ManyToManyField у которых более 10
элементов. Также вы можете использовать
filter_horizontal для нескольких полей, указав
их имена в кортеже.
Классы ModelAdmin так же поддерживает
опцию filter_vertical. Она работает так же, как
и filter_horizontal, но поля располагаются
вертикально. Используйте то, что вам больше нравится.
Опции filter_horizontal и
filter_vertical работают только с полями
ManyToManyField, не с
ForeignKey. По умолчанию, интерфейс
администратора использует <select> для
полей ForeignKey, но, так же как и для
поля ManyToManyField, иногда вы не
хотите видеть все объекты в выпадающем списке. Например, если
в вашей базе книг будут тысячи авторов, форма добавления книг
будет вынуждена загружать всех авторов в выпадающий список.
Методом для решения этой задачи является использование опции
raw_id_fields. Укажите для неё кортеж с именами
полей ForeignKey и эти поля будут
отображаться простым текстовым полем (<input type="text">) вместо
<select>. (См. рисунок «Страница списка редактирования книг с опцией raw_id_fields.».)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
filter_horizontal = ('authors',)
raw_id_fields = ('publisher',)
Что вы будете вводить в это поле? Идентификатор издателя. Учитывая то, что люди не могут запомнить идентификаторы из базы данных, рядом находится иконка с увеличительным стеклом, которую вы можете нажать для отображения окна, на котором вы можете выбрать требуемого издателя.
| Пред. | Уровень выше | След. |
| Настройка меток полей | Начало | Пользователи, группы и права |
12 комментариев | Оставьте комментарий
Наделал скриншотов, которые нужны на этой странице, но обрабатывать напильником лениво (т.е. в скриншотах полностью весь экран ;-), если они (такие скриншоты) нужны, то пишите - вышлю.
П.С. сначала написал тоже самое со страницы /feedback, но пришла ошибка - "Mail delivery failed: returning message to sender" от mailer-daemon@.
Выполняя все рекомендации книги заметил 2 момента.
1. Регистронезависимый поиск работает только для латиницы. При работе с кирилицей нужно указывать только точное название.
2. При использовании последней указанной здесь опции, raw_id_fields = ('publisher',), получается что при нажатии на иконку увеличительного стекла переходишь в форму редактирования издателей, а выбрать их там не можешь. Вибирать можно только указав конкретное число в поле. А, учитывая предыдущие действия, номер издателя ты не видишь, и издатели идут не по порядку id, а упорядочены по названию, то и понять, кто из них какой номер имеет, тоже нельзя... :)
Не знаю, может чего не так делал.
> 1. Регистронезависимый поиск работает только для латиницы. При работе с кирилицей нужно указывать только точное название.
Это зависит от БД. Django просто строит запрос и возврает результат. Иногда даже на странности разных БД забивают и не модифицируют результат.
Столкнулся с ошибкой: "Caught AttributeError while rendering: 'unicode' object has no attribute 'year'."
Вот что я сделал:
1. Согласно инструкции этой книги, в файл admin.py добавил строчку для класса BookAdmin:
last_filter = ('publication_date',)
2. Зашел в админку.
3. Нажал на категорию Books нашего приложения Books.
Может, кто-нибудь подскажет, как это исправить? :)
Ребята, простите за ошибку. Появление указанной ошибки произошло после добавления строчки date_hierarchy = 'publication_date'
Никак не могу понять, в чем дело...
Ура! Нашел решение проблемы! Как вы помните, у меня возникала ошибка при добавлении записи date_hierarchy = 'publication date'. Вот ошибка: "Caught AttributeError while rendering: 'unicode' object has no attribute 'year'."
Причина ошибки: Неверно задано свойство поля 'publication_date'. Необходимо, чтобы оно было date, а не varchar(255), как было у меня.
Чтобы задать это для MySQL выполните команду:
ALTER TABLE books_book MODIFY books_book.publication_date date NULL;
Ответ на voan
Наделал скриншотов, которые нужны на этой странице, но обрабатывать напильником лениво (т.е. в скриншотах полностью весь экран ;-), если они (такие скриншоты) нужны, то пишите - вышлю.
П.С. сначала написал тоже самое со страницы /feedback, но пришла ошибка - "Mail delivery failed: returning message to sender" от mailer-daemon@.
To tv:
Все там можно выбирать - нажимаешь на ссылку с именем нужного автора (как для редактирование) и его id выбирается автоматически.
Ответ на savao
Выполняя все рекомендации книги заметил 2 момента.
1. Регистронезависимый поиск работает только для латиницы. При работе с кирилицей нужно указывать только точное название.
2. При использовании последней указанной здесь опции, raw_id_fields = ('publisher',), получается что при нажатии на иконку увеличительного стекла переходишь в форму редактирования издателей, а выбрать их там не можешь. Вибирать можно только указав конкретное число в поле. А, учитывая предыдущие действия, номер издателя ты не видишь, и издатели идут не по порядку id, а упорядочены по названию, то и понять, кто из них какой номер имеет, тоже нельзя... :)
Не знаю, может чего не так делал.
Что то я напутал и не туда нажал. Предыдущий пост естественно для savao.
Ответ на savao
Выполняя все рекомендации книги заметил 2 момента.
1. Регистронезависимый поиск работает только для латиницы. При работе с кирилицей нужно указывать только точное название.
2. При использовании последней указанной здесь опции, raw_id_fields = ('publisher',), получается что при нажатии на иконку увеличительного стекла переходишь в форму редактирования издателей, а выбрать их там не можешь. Вибирать можно только указав конкретное число в поле. А, учитывая предыдущие действия, номер издателя ты не видишь, и издатели идут не по порядку id, а упорядочены по названию, то и понять, кто из них какой номер имеет, тоже нельзя... :)
Не знаю, может чего не так делал.
все по тому же шаблону и id видно
class PublisherAdmin(admin.ModelAdmin):
list_display = ('id', 'name')
admin.site.register(Publisher, PublisherAdmin)
Обьясните чайнику пожалуйста, как можна оставить поля 'first_name' и 'last_name' в одной колонке, а email во второй! list_display = ('first_name', 'last_name', 'email') - здесь в примере мы задаем 3 колонки!
Ответ на v_bratkev
Обьясните чайнику пожалуйста, как можна оставить поля 'first_name' и 'last_name' в одной колонке, а email во второй! list_display = ('first_name', 'last_name', 'email') - здесь в примере мы задаем 3 колонки!
Вопросы задавать на форуме.
Боже, какой хренью я раньше занимался.... почему сразу нельзя было Python с Django учить..