Spec-Zone.ru › Django 1.8

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

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

Философия

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

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

Админ-панель не предназначена для использования посетителями сайта. Она предназначена для менеджеров сайта.

Создание администраторского пользователя

Сначала нам нужно создать пользователя, который может войти в администраторский сайт. Выполните следующую команду:

$ python manage.py createsuperuser

Введите желаемое имя пользователя и нажмите Enter.

Username: admin

Затем вам будет предложено ввести желаемый адрес электронной почты:

Email address: admin@example.com

Последний шаг — ввести пароль. Вам будет предложено дважды ввести пароль, второй раз для подтверждения первого.

Password: **********
Password (again): *********
Superuser created successfully.

Запуск сервера разработки

Администраторский сайт Django активирован по умолчанию. Давайте запустим сервер разработки и изучим его.

Как следует из Урока 1, запустить сервер разработки можно следующим образом:

$ python manage.py runserver

Теперь откройте веб-браузер и перейдите по адресу «/admin/» на вашем локальном домене, например, http://127.0.0.1:8000/admin/. Вы должны увидеть экран входа в систему администратора:

Django admin login screen

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

Не совпадает с тем, что вы видите?

Если в этот момент вместо вышеупомянутой страницы входа в систему вы получаете страницу с ошибкой, например:

ImportError at /admin/
cannot import name patterns
...

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

Вход в администраторскую панель

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

Django admin index page

Вы должны увидеть несколько типов редактируемого контента: группы и пользователи. Они предоставляются django.contrib.auth — фреймворком аутентификации, поставляемым с Django.

Настройка приложения poll для редактирования в админке

Но где наше приложение poll? Его нет на главной странице админ-панели.

Всего одно действие: нам нужно сказать админке, что объекты Question имеют административный интерфейс. Для этого откройте файл polls/admin.py, и измените его следующим образом:

from django.contrib import admin

from .models import Question

admin.site.register(Question)

Исследуйте бесплатные возможности администрирования

Теперь, когда мы зарегистрировали Question, Django знает, что оно должно быть отображено на главной странице админ-панели:

Django admin index page, now with polls displayed

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

Polls change list page

Нажмите на вопрос «Что происходит?», чтобы отредактировать его:

Editing form for question object

Следует отметить следующее:

  • Форма автоматически генерируется из модели Question.
  • Разные типы полей модели (DateTimeField, CharField) соответствуют соответствующему виджету HTML-ввода. Каждый тип поля знает, как отобразить себя в Django admin.
  • Каждое DateTimeField получает бесплатные JavaScript-ярлыки. Для дат доступен ярлык «Сегодня» и всплывающее календарное окно, а для времени — ярлык «Сейчас» и удобное всплывающее окно, которое отображает часто вводимое время.

В нижней части страницы доступны несколько вариантов:

  • Сохранить — сохраняет изменения и возвращается на страницу «список изменений» для этого типа объектов.
  • Сохранить и продолжить редактирование — сохраняет изменения и перезагружает страницу администрирования для этого объекта.
  • Сохранить и добавить другой — сохраняет изменения и загружает новую пустую форму для этого типа объекта.
  • Удалить — отображает страницу подтверждения удаления.

Если значение «Дата публикации» не соответствует времени, когда вы создали вопрос в Уроке 1, это, вероятно, означает, что вы забыли установить правильное значение для настройки TIME_ZONE. Измените его, перезагрузите страницу и проверьте, что отображается правильное значение.

Измените «Дату публикации», нажав на ярлыки «Сегодня» и «Сейчас». Затем нажмите «Сохранить и продолжить редактирование». Затем нажмите «История» в правом верхнем углу. Вы увидите страницу, на которой перечислены все изменения, внесённые в этот объект через Django admin, с отметкой времени и именем пользователя, который внес изменение:

History page for question object

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

Потратьте несколько минут, чтобы полюбоваться всем кодом, который вам не пришлось писать. Зарегистрировав модель Question с помощью admin.site.register(Question), Django смог создать представление формы по умолчанию. Часто вам захочется настроить внешний вид и работу формы администрирования. Вы сделаете это, указав 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

Вы можете назначать произвольные HTML-классы каждому набору полей. Django предоставляет класс "collapse" , который отображает определённый набор полей первоначально свёрнутым. Это полезно, когда у вас длинная форма, содержащая ряд полей, которые не часто используются:

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]

admin.site.register(Question, QuestionAdmin)
Fieldset is initially collapsed

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

Хорошо, у нас есть страница администрирования вопросов. Но объект Question имеет несколько Choices, а страница администрирования не отображает варианты.

Пока нет.

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

from django.contrib import admin

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

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

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 из Урока 1:

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):
        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: фильтры с помощью 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 admin работает на основе самого 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 проверяет при загрузке шаблонов Django; это путь поиска.

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

Где находятся исходные файлы Django?

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

$ python -c "
import sys
sys.path = sys.path[1:]
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 admin.

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

Шаблон для настройки — admin/index.html. (Сделайте то же, что и с admin/base_site.html в предыдущем разделе — скопируйте его из каталога по умолчанию в ваш настраиваемый каталог шаблонов.) Откройте файл, и вы увидите, что он использует переменную шаблона app_list. Эта переменная содержит каждое установленное приложение Django. Вместо этого вы можете ввести ссылки на страницы администрирования, специфичные для объектов, каким способом вы посчитаете наиболее подходящим. Снова, не беспокойтесь, если вы не понимаете язык шаблонов — мы рассмотрим его подробнее в Уроке 3.

Когда вы освоитесь с админ-сайтом, прочитайте часть 3 этого руководства, чтобы начать работу с публичными представлениями опросов.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/intro/tutorial02/

Spec-Zone.ru

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