Spec-Zone.ru › Django 6.0

Создание первого приложения Django, часть 7

Это руководство продолжает тему, на которой мы остановились в руководстве 6. Мы продолжим работу над веб-приложением для опросов и сосредоточимся на настройке автоматически созданного сайта администрирования Django, с которым мы впервые познакомились в руководстве 2.

Где получить помощь:

Если у вас возникли трудности при прохождении этого руководства, обратитесь к разделу Получение помощи в FAQ.

Настройка формы администрирования

Зарегистрировав модель Question в admin.site.register(Question), Django смог создать представление формы по умолчанию. Часто возникает необходимость настроить внешний вид и работу формы администрирования. Для этого нужно указать Django нужные параметры при регистрации объекта.

Давайте посмотрим, как это работает, изменив порядок полей в форме редактирования. Замените строку admin.site.register(Question) на:

polls/admin.py
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().

Это изменение помещает поле «Дата публикации» перед полем «Вопрос»:

Fields have been reordered

При наличии всего двух полей это не особенно впечатляет, но для форм администрирования с десятками полей выбор понятного порядка — важная деталь, повышающая удобство использования.

Раз уж мы заговорили о формах с десятками полей, возможно, вам будет удобнее разделить форму на группы полей:

polls/admin.py
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 — это заголовок группы полей. Теперь наша форма выглядит так:

Form has fieldsets now

Добавление связанных объектов

Итак, у нас есть страница администрирования вопросов, но у Question может быть несколько Choice, а на странице администрирования варианты ответов не отображаются.

Пока.

Есть два способа решить эту проблему. Первый — зарегистрировать Choice в администрировании так же, как мы это сделали для Question:

polls/admin.py
from django.contrib import admin

from .models import Choice, Question

# ...
admin.site.register(Choice)

Теперь в администрировании Django доступен пункт «Варианты ответов». Форма «Добавить вариант ответа» выглядит так:

Choice admin page

В этой форме поле «Вопрос» — это список выбора, содержащий все вопросы из базы данных. Django знает, что ForeignKey нужно представить в администрировании в виде поля <select>. В нашем случае на этом этапе существует только один вопрос.

Также обратите внимание на ссылку «Добавить ещё один вопрос» рядом с полем «Вопрос». Такая возможность предоставляется автоматически для каждого объекта, связанного с другим объектом отношением ForeignKey. Нажав «Добавить ещё один вопрос», вы откроете всплывающее окно с формой «Добавить вопрос». Если вы добавите вопрос в этом окне и нажмёте «Сохранить», Django сохранит вопрос в базе данных и динамически добавит его как выбранный вариант в открытую форму «Добавить вариант ответа».

Но на самом деле это неэффективный способ добавления в систему объектов Choice. Было бы удобнее добавлять сразу несколько вариантов ответов при создании объекта Question. Давайте это исправим.

Удалите вызов register() для модели Choice. Затем измените код регистрации Question следующим образом:

polls/admin.py
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 вариантов ответа».

Откройте страницу «Добавить вопрос», чтобы посмотреть, как это выглядит:

Add question page now has choices on it

Это работает следующим образом: предусмотрено три поля для связанных вариантов ответа — как указано в extra, — и каждый раз, когда вы возвращаетесь на страницу изменения уже созданного объекта, появляются ещё три дополнительных поля.

В конце трёх имеющихся полей вы найдёте ссылку «Добавить ещё один вариант ответа». Нажав её, вы добавите новое поле. Чтобы удалить добавленное поле, нажмите на крестик в его верхнем правом углу. На изображении показано добавленное поле:

Additional slot added dynamically

Однако есть небольшая проблема. Для отображения всех полей ввода связанных объектов Choice требуется много места на экране. Поэтому Django предлагает табличный способ отображения связанных объектов в строках формы. Чтобы использовать его, измените объявление ChoiceInline следующим образом:

polls/admin.py
class ChoiceInline(admin.TabularInline): ...

С этим TabularInline (вместо StackedInline) связанные объекты отображаются в более компактном табличном формате:

Add question page now has more compact choices

Обратите внимание на дополнительный столбец «Удалить?», который позволяет удалять строки, добавленные с помощью кнопки «Добавить ещё один вариант ответа», а также уже сохранённые строки.

Настройка списка объектов в администрировании

Теперь страница администрирования вопросов выглядит хорошо. Давайте внесём несколько изменений на страницу «списка объектов» — ту, на которой отображаются все вопросы в системе.

Сейчас она выглядит так:

Polls change list page

По умолчанию Django отображает str() каждого объекта. Но иногда было бы полезнее показывать отдельные поля. Для этого используйте параметр администрирования list_display — список имён полей, которые будут отображаться в виде столбцов на странице списка объектов:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date"]

Для полноты картины добавим также метод was_published_recently() из руководства 2:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date", "was_published_recently"]

Теперь страница списка вопросов выглядит так:

Polls change list page, updated

Вы можете щёлкнуть заголовок столбца, чтобы отсортировать список по соответствующим значениям, — за исключением заголовка was_published_recently, поскольку сортировка по результату произвольного метода не поддерживается. Также обратите внимание, что заголовком столбца was_published_recently по умолчанию служит имя метода (подчёркивания заменяются пробелами), а в каждой строке отображается строковое представление результата.

Это можно улучшить, добавив к методу декоратор display() (изменив файл polls/models.py, созданный в руководстве 2), например так:

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:

Polls change list page, updated

Тип отображаемого фильтра зависит от типа поля, по которому выполняется фильтрация. Поскольку 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 в каталоге djangotutorial. Шаблоны могут находиться в любом месте файловой системы, доступном Django. (Django работает от имени того же пользователя, что и сервер.) Однако хорошей практикой считается хранить шаблоны внутри проекта.

Откройте файл настроек (не забудьте, что это mysite/settings.py) и добавьте параметр DIRS в настройку TEMPLATES:

mysite/settings.py
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "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, разумнее было бы изменять шаблоны приложения, а не проекта. Тогда вы могли бы подключить приложение polls к любому новому проекту и быть уверены, что оно найдёт необходимые пользовательские шаблоны.

Подробнее о том, как 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/6.0/intro/tutorial07/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API