Spec-Zone.ru › Django 2.2

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

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

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

Зарегистрировав модель 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)

Вы будете следовать этому шаблону – создавайте класс модели администратора, затем передавайте его в качестве второго аргумента в 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 – и каждый раз, когда вы возвращаетесь на страницу «Изменить» для уже созданного объекта, у вас появляются еще три дополнительных места.

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

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

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

polls/models.py
class Question(models.Model):
    # ...
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    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: фильтры с помощью 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 administration» в верхней части каждой страницы администратора нелепо. Это просто текст-заполнитель.

Однако это легко изменить, используя систему шаблонов Django. Django администратор питается самим 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 — это список каталогов файловой системы, которые необходимо проверить при загрузке шаблонов 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/2.2/intro/tutorial07/

Spec-Zone.ru

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