Создание вашего первого приложения Django, часть 7
Этот учебник продолжает то, где закончился Учебник 6. Мы продолжаем приложение Web-poll и сосредоточимся на настройке автоматически сгенерированного администраторского сайта Django, с которым мы впервые познакомились в Учебнике 2.
Где получить помощь:
Если у вас возникнут проблемы с прохождением этого учебника, обратитесь к разделу Получение помощи раздела FAQ.
Настройка формы администратора
Зарегистрировав модель Question с помощью admin.site.register(Question), Django смог создать стандартную форму представления. Часто вам захочется настроить внешний вид и работу формы администратора. Для этого вы укажете желаемые параметры при регистрации объекта.
Давайте посмотрим, как это работает, переупорядочив поля в форме редактирования. Замените строку admin.site.register(Question) на:
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question_text']
admin.site.register(Question, QuestionAdmin)
Вы будете следовать этой схеме — создадите класс модели администратора, а затем передадите его как второй аргумент в admin.site.register() — всякий раз, когда вам нужно изменить параметры администратора для модели.
Это конкретное изменение выше помещает поле «Дата публикации» перед полем «Вопрос»:
Это не впечатляет с двумя полями, но для форм администратора с десятками полей выбор интуитивно понятного порядка является важным аспектом удобства использования.
И, говоря о формах с десятками полей, вы можете разделить форму на группы полей:
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Question, QuestionAdmin)
Первый элемент каждой кортежа в fieldsets — это заголовок группы полей. Вот как выглядит наша форма сейчас:
Добавление связанных объектов
Пока что нет.
Есть два способа решения этой проблемы. Первый — зарегистрировать Choice в администраторе так же, как мы это сделали с Question:
from django.contrib import admin from .models import Choice, Question # ... admin.site.register(Choice)
Теперь «Варианты» доступны в Django администраторе. Форма «Добавить вариант» выглядит так:
В этой форме поле «Вопрос» — выпадающий список, содержащий все вопросы в базе данных. Django знает, что ForeignKey должен отображаться в администраторе как поле <select>. В нашем случае в данный момент существует только один вопрос.
Обратите также внимание на ссылку «Добавить ещё» рядом с «Вопрос». Каждый объект с отношением ForeignKey к другому объекту получает это бесплатно. При нажатии «Добавить ещё» откроется всплывающее окно с формой «Добавить вопрос». Если вы добавите вопрос в этом окне и нажмёте «Сохранить», Django сохранит вопрос в базе данных и динамически добавит его как выбранный вариант в форме «Добавить вариант», которую вы сейчас видите.
Но на самом деле это неэффективный способ добавления Choice объектов в систему. Было бы лучше, если бы вы могли добавить сразу несколько вариантов при создании объекта Question. Давайте сделаем это.
Удалите вызов register() для модели Choice. Затем отредактируйте код регистрации Question следующим образом:
from django.contrib import admin
from .models import Choice, Question
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
admin.site.register(Question, QuestionAdmin)
Это говорит Django: «Choice объекты редактируются на странице администратора Question. По умолчанию предоставьте достаточно полей для 3 вариантов».
Загрузите страницу «Добавить вопрос», чтобы увидеть, как это выглядит:
Это работает так: есть три слота для связанных вариантов — как указано в extra — и каждый раз, когда вы возвращаетесь на страницу «Изменить» для уже созданного объекта, вы получаете ещё три дополнительных слота.
В конце трех текущих слотов вы найдете ссылку «Добавить ещё вариант». Если вы нажмете на неё, будет добавлен новый слот. Если вы хотите удалить добавленный слот, вы можете нажать на крестик в правом верхнем углу добавленного слота. На этой картинке показан добавленный слот:
Однако есть одна небольшая проблема. Отображение всех полей для ввода связанных объектов Choice занимает много места на экране. По этой причине Django предлагает табличный способ отображения связанных объектов в строках. Для этого измените объявление ChoiceInline следующим образом:
class ChoiceInline(admin.TabularInline):
#...
С этим TabularInline (вместо StackedInline) связанные объекты отображаются в более компактном, табличном формате:
Обратите внимание, что есть дополнительный столбец «Удалить?», который позволяет удалять строки, добавленные с помощью кнопки «Добавить ещё вариант», а также строки, которые уже были сохранены.
Настройка списка изменений администратора
Теперь, когда страница администратора «Вопрос» выглядит хорошо, давайте внесем некоторые изменения на странице «Список изменений» — той, которая отображает все вопросы в системе.
Вот как она выглядит на данном этапе:
По умолчанию Django отображает str() каждого объекта. Но иногда было бы полезнее отображать отдельные поля. Для этого используйте опцию администратора list_display, которая представляет собой кортеж имен полей для отображения в виде столбцов на странице «Список изменений» объекта:
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date')
Для большей наглядности, давайте также включим метод was_published_recently() из Учебника 2:
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')
Теперь страница списка изменений вопросов выглядит так:
Вы можете нажать на заголовки столбцов, чтобы отсортировать по этим значениям — за исключением заголовка was_published_recently, потому что сортировка по результату произвольного метода не поддерживается. Также обратите внимание, что заголовок столбца was_published_recently по умолчанию — имя метода (с подчёркиваниями, заменёнными пробелами), и каждая строка содержит строковое представление вывода.
Вы можете улучшить это, используя декоратор display() на этом методе (в polls/models.py), как показано ниже:
from django.contrib import admin
class Question(models.Model):
# ...
@admin.display(
boolean=True,
ordering='pub_date',
description='Published recently?',
)
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
Дополнительную информацию о свойствах, настраиваемых с помощью декоратора, см. в list_display.
Измените файл polls/admin.py ещё раз и добавьте улучшение к странице списка изменений Question: фильтры с использованием list_filter. Добавьте следующую строку в QuestionAdmin:
list_filter = ['pub_date']
Это добавит боковую панель «Фильтр», позволяющую пользователям фильтровать список изменений по полю pub_date:
Тип отображаемого фильтра зависит от типа поля, по которому вы фильтруете. Поскольку pub_date является DateTimeField, Django знает, какие параметры фильтра использовать: «Любая дата», «Сегодня», «Прошедшие 7 дней», «Текущий месяц», «Текущий год».
Это выглядит хорошо. Давайте добавим возможность поиска:
search_fields = ['question_text']
Это добавляет поле поиска в верхней части списка изменений. Когда кто-то вводит поисковые запросы, Django будет искать по полю question_text. Вы можете использовать любое количество полей — хотя, поскольку используется запрос LIKE , ограничение количества полей поиска разумным числом сделает поиск в базе данных проще.
Сейчас также стоит отметить, что списки изменений предоставляют бесплатную постраничную навигацию. По умолчанию отображается 100 элементов на странице. Change list pagination, search boxes, filters, date-hierarchies и column-header-ordering работают вместе так, как вы ожидаете.
Настройка внешнего вида администратора
Очевидно, что «Администрирование Django» вверху каждой страницы администратора — это нелепо. Это просто текст-заполнитель.
Вы можете его изменить, используя систему шаблонов Django. Django администратор работает на основе самого Django, и его интерфейсы используют собственную систему шаблонов Django.
Настройка шаблонов вашего проекта
Создайте директорию templates в директории вашего проекта (той, которая содержит manage.py). Шаблоны могут храниться в любой точке вашей файловой системы, доступной для Django. (Django выполняется под учетной записью пользователя, под которым работает ваш сервер). Однако рекомендуется хранить шаблоны внутри проекта.
Откройте файл настроек (mysite/settings.py, помните) и добавьте параметр DIRS в настройку TEMPLATES:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DIRS — это список директорий файловой системы, которые проверяются при загрузке шаблонов Django; это путь поиска.
Организация шаблонов
Так же, как и статические файлы, мы можем хранить все шаблоны вместе в одной большой директории шаблонов, и это будет работать идеально. Однако шаблоны, относящиеся к конкретному приложению, следует размещать в соответствующей директории шаблонов приложения (например, polls/templates) вместо директории проекта (templates). Более подробно мы обсудим это в учебнике по многократно используемым приложениям, объясняя *почему* мы так делаем.
Теперь создайте директорию с именем admin внутри templates и скопируйте шаблон admin/base_site.html из директории шаблонов по умолчанию Django админки в исходном коде Django (django/contrib/admin/templates) в эту директорию.
Где находятся исходные файлы Django?
Если у вас возникнут трудности с поиском исходных файлов Django на вашей системе, выполните следующую команду:
$ python -c "import django; print(django.__path__)"
...\> py -c "import django; print(django.__path__)"
Затем отредактируйте файл и замените {{ site_header|default:_('Django administration') }} (включая фигурные скобки) именем вашего сайта по своему усмотрению. В итоге у вас получится фрагмент кода вроде:
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}
Мы используем этот подход, чтобы показать вам, как переопределять шаблоны. В реальном проекте вы, скорее всего, будете использовать атрибут django.contrib.admin.AdminSite.site_header для более удобной настройки.
Этот файл шаблона содержит много текста, например, {% block branding %} и {{ title }}. Теги {% и {{ являются частью языка шаблонов Django. Когда Django отображает admin/base_site.html, этот язык шаблонов будет вычисляться для создания итоговой HTML-страницы, как мы видели в Учебнике 3.
Обратите внимание, что вы можете переопределить любые стандартные шаблоны админки Django. Для переопределения шаблона сделайте то же, что вы делали с base_site.html — скопируйте его из директории по умолчанию в вашу пользовательскую директорию и внесите изменения.
Настройка шаблонов вашего приложения
Внимательные читатели спросят: но если DIRS изначально был пустым, как Django находил стандартные шаблоны админки? Ответ заключается в том, что, поскольку APP_DIRS установлен в True, Django автоматически ищет поддиректорию templates/ внутри каждого пакета приложения, чтобы использовать её как резерв (не забудьте, что django.contrib.admin — это приложение).
Наше приложение опросов не очень сложное и не нуждается в пользовательских шаблонах админки. Но если бы оно стало более сложным и потребовало модификации стандартных шаблонов админки Django для некоторых своих функций, было бы более целесообразно модифицировать шаблоны *приложения*, а не *проекта*. Таким образом, вы могли бы включить приложение опросов в любой новый проект и быть уверены, что оно найдёт необходимые пользовательские шаблоны.
Дополнительную информацию о том, как Django находит свои шаблоны, см. в документации по загрузке шаблонов.
Настройка главной страницы админки
Аналогично, вы можете настроить внешний вид главной страницы админки Django.
По умолчанию она отображает все приложения в INSTALLED_APPS, которые были зарегистрированы в приложении админки, в алфавитном порядке. Возможно, вам захочется внести существенные изменения в макет. В конце концов, главная страница админки, скорее всего, является самой важной страницей, и она должна быть удобной в использовании.
Шаблоном для настройки является admin/index.html. (Сделайте то же, что и с admin/base_site.html в предыдущем разделе — скопируйте его из директории по умолчанию в вашу пользовательскую директорию шаблонов). Откройте файл и вы увидите, что он использует переменную шаблона app_list. Эта переменная содержит все установленные приложения Django. Вместо этого вы можете жестко закодировать ссылки на страницы админки для конкретных объектов любым способом, который вам кажется лучшим.
Что дальше?
На этом заканчивается учебник для начинающих. Тем временем вы можете ознакомиться с рекомендациями о том, куда двигаться дальше.
Если вы знакомы с пакетированием Python и хотите узнать, как сделать приложение опросов «многократно используемым приложением», ознакомьтесь с Расширенный учебник: Как создавать многократно используемые приложения.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/intro/tutorial07/