Создание вашего первого приложения Django, часть 7
Этот учебник начинается там, где закончился Урок 6. Мы продолжаем веб-приложение опроса и сосредоточимся на настройке автоматически сгенерированной Django-админ-панели, которую мы впервые изучили в Уроке 2.
Где получить помощь:
Если у вас возникли трудности с этим учебником, перейдите к разделу Получение помощи в разделе FAQ.
Настройка формы администрирования
Регистрируя модель Question с admin.site.register(Question), Django смог создать представление формы по умолчанию. Часто вам захочется настроить внешний вид и работу формы администрирования. Вы сделаете это, указав 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, и каждый раз, когда вы возвращаетесь на страницу «Изменить» для уже созданного объекта, вы получаете ещё три дополнительных места.
В конце трёх текущих мест вы найдёте ссылку «Добавить ещё один вариант». Если вы нажмёте на неё, будет добавлено новое место. Если вы хотите удалить добавленное место, вы можете нажать на X в правом верхнем углу добавленного места. На этом изображении показано добавленное место:
Однако есть одна небольшая проблема. Для отображения всех полей для ввода связанных 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.
END_OF_DOCUMENT_MARKERНастройка шаблонов вашего проекта
Создайте директорию 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 проверяет при загрузке шаблонов; это путь поиска.
Организация шаблонов
Так же, как и с файлами статики, мы могли бы поместить все шаблоны вместе, в один большой каталог templates, и это отлично сработает. Тем не менее, шаблоны, относящиеся к конкретному приложению, должны быть размещены в каталоге шаблонов этого приложения (например, 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/4.0/intro/tutorial07/