Spec-Zone.ru › Django 1.10

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

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

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

Зарегистрировав модель Question с admin.site.register(Question), 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() — всякий раз, когда вам нужно изменить опции администратора для модели.

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

Fields have been reordered

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

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

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. Это легко:

from django.contrib import admin

from .models import Choice, Question
# ...
admin.site.register(Choice)

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

Choice admin page

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

Обратите также внимание на ссылку «Добавить ещё» рядом с «Вопрос». Каждый объект с отношением 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 вариантов».

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

Add question page now has choices on it

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

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

Additional slot added dynamically

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

class ChoiceInline(admin.TabularInline):
    #...

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

Add question page now has more compact choices

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

Настройка списка изменений администратора

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

Вот как она выглядит на данный момент:

Polls change list page

По умолчанию 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')

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

Polls change list page, updated

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

Вы можете улучшить это, добавив к методу (в 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» вверху каждой страницы администратора — это нелепо. Это просто текст-заполнитель.

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

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

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

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

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__)"

Затем просто отредактируйте файл и замените {{ 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/1.10/intro/tutorial07/

Spec-Zone.ru

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