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

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

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

После регистрации модели Question с помощью admin.site.register(Question) 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)

Если вам необходимо настроить интерфейс администратора для модели, создайте ModelAdmin, затем передайте его в admin.site.register().

Пример выше переместит поле “Publication date” перед “Question”:

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

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

Теперь, когда страница добавления и редактирования вопроса выглядит хорошо, мы может улучшить страницу списка вопросов.

Сейчас она выглядит следующим образом:

Polls change list page

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

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

Также для удобства добавим метод was_published_recently() из второй части учебника:

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 по умолчанию содержит название метода (где подчеркивание заменено на пробелы), а значения являются результатами выполнения метода.

Вы можете исправить это, указав несколько атрибутов для метода (в файле polls/models.py):

polls/models.py
class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

Подробнее об этих атрибутах можно узнать в описании list_display.

Давайте снова отредактируем файл polls/admin.py и улучшим страницу списка объектов Question`: добавим фильтрацию, используя :attr:`~django.contrib.admin.ModelAdmin.list_filter`. Добавьте следующие строки в ``QuestionAdmin:

list_filter = ['pub_date']

Это добавило справа панель фильтрации, которая позволит фильтровать записи по полю pub_date:

Polls change list page, updated

Вид фильтра зависит от типа поля, к которому он применяется. Так как pub_date представлено DateTimeField, Django отображает подходящие опции для фильтрации: “Any date”, “Today”, “Past 7 days”, “This month”, “This year”.

Теперь добавим возможность поиска по записям:

search_fields = ['question_text']

Теперь в верхней части страницы появилось поле для поиска. При вводе запроса в это поле Django выполнит поиск по полю question_text. Вы можете указать сколько угодно полей, но, учитывая что используется запрос LIKE, их количество должно быть разумным, чтобы запрос не выполнялся слишком долго.

Также страница списка объектов содержит постраничное отображение. По умолчанию показывается 100 записей на страницу. Изменение постраничного отображения, поиска, фильтров, иерархия по дате и сортировка отлично работают вместе.

Настройка внешнего вида интерфейса администратора

“Django administration” на каждой странице выглядит не очень привлекательно. Это просто текст по умолчанию.

Его легко поменять, используя систему шаблонов Django. Админка использует стандартную систему шаблонов Django.

Настройка шаблонов проекта

Создайте каталог templates в каталоге вашего проекта (это тот, который содержит файл manage.py). Шаблоны могут находиться где угодно в файловой системе, пока у Django есть доступ к ним. (Django запускается от пользователя, от которого запущен веб-сервер.) Одна, хранить шаблоны в проекте удобно и является хорошей практикой.

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

mysite/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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 содержит список каталогов с шаблонами.

Организация шаблонов

Как и в случае со статическими файлами, мы можем хранить все шаблоны вместе в одном большом каталоге, и это может отлично работать. Однако, шаблоны, которые относятся к определенному приложению, необходимо хранить в каталоге шаблонов приложения (например polls/templates), а не каталоге шаблонов проекта (templates). Мы подробнее расскажем зачем это делать в разделе о о повторно применяемых приложениях.

Теперь создайте каталог admin внутри templates, и скопируйте в этот каталог шаблон admin/base_site.html из каталога шаблонов админки непосредственно из исходного кода Django (django/contrib/admin/templates).

Где найти исходный код Django?

Если вы не можете найти исходный код Django, выполните следующую команду:

$ python -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 страницы, как это было показано в третьем разделе.

Вы можете переопределить любой шаблон админки Django. Чтобы переопределить шаблон, сделайте все то же, что и с шаблоном base_site.html – скопируйте шаблон в ваш каталог шаблонов и измените его.

Настройка шаблонов вашего приложения

Внимательные читатели спросят: если DIRS по умолчанию ничего не содержит, как Django находит стандартные шаблоны админки? Ответ следующий: так как APP_DIRS равен True, Django автоматически ищет каталог templates/ в каждом приложении (не забываем, что django.contrib.admin является приложением).

Наше приложение для опросов не сложное и не требует переопределения шаблонов. Но если оно станет сложнее и потребует переопределения шаблонов админки, лучше переопределять их для приложения, а не всего проекта. В таком случае вы можете добавить приложение к любому проекту, и быть уверенным, что будут использоваться модифицированные шаблоны.

Смотрите раздел о загрузке шаблонов, чтобы узнать как Django ищет шаблоны.

Настройка главной страницы интерфейса администратора

Вам может понадобиться настроить главную страницу админки Django.

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

Необходимо переопределить шаблон admin/index.html. (Как и для admin/base_site.html, скопируйте этот шаблон в свой проект). Откройте файл и вы увидите, что там используется переменная app_list. Она содержим все установленные приложения. Вместо использования этой переменной, вы можете “захардкодить” ссылки к страницам, если считаете, что так будет лучше.

Что дальше?

На этом учебник для новичков окончен. Вам следует обратить внимание на раздел Куда двигаться далее.

Если вы знакомы с пакетами Python и хотите сделать “независимое приложение”, изучите раздел Углублённый материал: Как создать повторно применяемое приложение.