Написание вашего первого приложения Django, часть 7
Этот учебник начинается там, где Учебник 6 закончился. Мы продолжаем веб-приложение опроса и сосредоточимся на настройке автоматически сгенерированной Django-панели администратора, которую мы впервые изучили в Учебнике 2.
Где получить помощь:
Если у вас возникли проблемы при прохождении этого учебника, перейдите к разделу Получение помощи FAQ.
Настройка формы администратора
Зарегистрировав модель Question с admin.site.register(Question), Django смог создать представление формы по умолчанию. Часто вам потребуется настроить внешний вид и работу формы администратора. Вы сделаете это, указав необходимые параметры при регистрации объекта.
Давайте посмотрим, как это работает, переупорядочив поля в форме редактирования. Замените строку admin.site.register(Question) на:
polls/admin.pyfrom 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() — всякий раз, когда вам нужно изменить параметры администратора для модели.
Это изменение помещает поле «Дата публикации» перед полем «Вопрос»:
Это не впечатляет с двумя полями, но для форм администратора с десятками полей выбор интуитивно понятного порядка — важная деталь удобства использования.
И говоря о формах с десятками полей, вы можете разбить форму на группы полей:
polls/admin.pyfrom 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:
polls/admin.pyfrom django.contrib import admin from .models import Choice, Question # ... admin.site.register(Choice)
Теперь «Варианты» доступен в Django администрировании. Форма «Добавить вариант» выглядит так:
В таком виде поле «Вопрос» — это выпадающий список, содержащий все вопросы в базе данных. Django знает, что ForeignKey должен быть представлен в админке в виде <select>-окна. В нашем случае на данный момент существует только один вопрос.
Обратите также внимание на ссылку «Добавить вопрос» рядом с «Вопрос». Все объекты со связью типа ForeignKey с другим объектом получают это автоматически. При нажатии на «Добавить другой вопрос» появится всплывающее окно с формой «Добавить вопрос». Если вы добавите вопрос в этом окне и нажмёте «Сохранить», Django сохранит вопрос в базе данных и динамически добавит его как выбранный вариант в форме «Добавить ответ», которую вы сейчас смотрите.
Однако на самом деле это неэффективный способ добавления Choice объектов в систему. Лучше бы вы могли добавлять сразу несколько вариантов ответов при создании Question объекта. Давайте это сделаем.
Удалите вызов register() для модели Choice. Затем отредактируйте код регистрации Question следующим образом:
polls/admin.pyfrom 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 вариантов ответа».
Загрузите страницу «Добавить вопрос», чтобы увидеть, как это выглядит:
Однако есть одна небольшая проблема. Для отображения всех полей для ввода связанных Choice объектов требуется много места на экране. По этой причине Django предлагает табличный способ отображения связанных объектов в строке. Для его использования, измените объявление ChoiceInline на:
polls/admin.pyclass ChoiceInline(admin.TabularInline): ...
С этим %%%CODE_BLOCK_32%% (вместо StackedInline), связанные объекты отображаются в более компактном, табличном формате:
Обратите внимание, что есть дополнительный столбец «Удалить?», который позволяет удалять строки, добавленные с помощью кнопки «Добавить ещё один выбор», а также строки, которые уже были сохранены.
Настройка списка изменений администрирования
Теперь, когда страница администрирования вопросов выглядит хорошо, давайте внесём некоторые изменения в страницу «список изменений» — ту, которая отображает все вопросы в системе.
Вот как она выглядит на данный момент:
По умолчанию Django отображает str() каждого объекта. Но иногда полезнее отображать отдельные поля. Для этого используйте опцию администрирования list_display, которая представляет собой список имён полей, которые должны отображаться в виде столбцов на странице списка изменений объекта:
polls/admin.pyclass QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date"]
Для большей надёжности, давайте также включим метод was_published_recently() из Урока 2:
polls/admin.pyclass QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date", "was_published_recently"]
Теперь страница списка изменений вопросов выглядит так:
Вы можете нажать на заголовки столбцов, чтобы отсортировать по этим значениям — за исключением заголовка was_published_recently, так как сортировка по результатам произвольного метода не поддерживается. Также обратите внимание, что заголовок столбца для was_published_recently по умолчанию — имя метода (с нижними подчеркиваниями, заменёнными пробелами), и каждая строка содержит строковое представление вывода.
Вы можете улучшить это, используя декоратор display() для этого метода (в polls/models.py), как показано ниже:
polls/models.pyfrom 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:
DateTimeField, Django знает, как предоставить соответствующие параметры фильтра: «Любая дата», «Сегодня», «Последние 7 дней», «Текущий месяц», «Текущий год».Всё идет хорошо. Добавим возможность поиска:
search_fields = ["question_text"]
Это добавляет поле поиска в верхней части списка изменений. Когда кто-то вводит поисковые термины, Django будет искать по полю question_text. Вы можете использовать любое количество полей — хотя, поскольку в фоновом режиме используется запрос LIKE, ограничение числа полей поиска разумными значениями упростит поиск для вашей базы данных.
Сейчас также стоит отметить, что списки изменений предоставляют вам бесплатную постраничную навигацию. По умолчанию отображается 100 элементов на странице. Change list pagination, search boxes, filters, date-hierarchies и column-header-ordering работают вместе так, как вы ожидаете.
Настройка внешнего вида админ-панели
Очевидно, наличие текста «Django administration» вверху каждой страницы администрирования — нелепость. Это просто заполнитель.
Однако вы можете изменить его, используя систему шаблонов Django. Django админ-панель основана на самом Django, и её интерфейсы используют собственную систему шаблонов Django.
Настройка шаблонов вашего проекта
Создайте директорию templates в директории вашего проекта (той, которая содержит manage.py). Шаблоны могут находиться в любой доступной Django части вашей файловой системы. (Django работает как пользователь, под которым работает ваш сервер). Однако, хранение шаблонов внутри проекта — хорошая практика.
Откройте файл настроек (mysite/settings.py, помните) и добавьте параметр DIRS в настройку TEMPLATES:
mysite/settings.pyTEMPLATES = [
{
"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 %}
<div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
{% if user.is_anonymous %}
{% include "admin/color_theme_toggle.html" %}
{% endif %}
{% 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. Вместо этого вы можете напрямую задать ссылки на страницы администрирования объектов любым способом, который вам кажется наилучшим.
Когда вы будете готовы, прочитайте 8-ю часть этого руководства, чтобы узнать, как использовать сторонние пакеты.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/intro/tutorial07/