Как работает административный интерфейс Django
Как же на самом деле работает административный интерфейс? Довольно просто.
Когда во время запуска сервера фреймворк Django загружает конфигурацию URL из файла urls.py, он выполняет инструкцию admin.auto- discover(), добавленную нами во время активации административного интерфейса. Эта функция обходит все элементы в списке приложений INSTALLED_APPS и в каждом из них отыскивает файл с именем admin.ру. Если файл найден, то выполняется находящийся в нем код.
В файле admin.ру для нашего приложения books каждый вызов метода admin.site.register() просто регистрирует одну из моделей в административном интерфейсе. А в списке моделей, доступных для редактирования, отображаются только явно зарегистрированные.
Приложение django.contrib.auth тоже включает файл admin.ру, потому- то и присутствуют в таблице строки Users и Groups. Регистрируются в административном интерфейсе и другие приложения из пакета django. contrib, такие как django.contrib.redirects, а также многие сторонние приложения Django, которые есть в Интернете.
Во всех остальных отношениях административный интерфейс - обычное приложение Django со своими моделями, шаблонами, представлениями и образцами URL. Чтобы добавить его в свой проект, нужно завести образцы URL точно так же, как вы делаете это для собственных представлений. Заглянув в каталог django/contrib/admin в своей копии дистрибутива Django, вы сможете изучить шаблоны, представления и образцы URL административного интерфейса, но не пытайтесь что-то изменять прямо там, потому что есть вполне достаточно официальных точек подключения, позволяющих настроить работу административного интерфейса под себя. (Если вы все-таки решитесь модифицировать это приложение, имейте в виду, что при чтении метаданных о моделях оно делает довольно хитрые вещи, поэтому на то, чтобы разобраться в коде, может уйти много времени.)
Как сделать поле необязательным
Немного поэкспериментировав с административным интерфейсом, вы заметите одно ограничение - в формах редактирования все поля должны быть заполнены, тогда как в действительности часто бывает желательно сделать некоторые поля необязательными. Пусть, например, поле email в модели Author следует сделать необязательным. Ведь в настоящем приложении не у всех авторов есть адрес электронной почты.
Чтобы сделать поле email необязательным, откройте модель Book (напомним, что она находится в файле mysite/books/models.py) и добавьте в описание поля email параметр blank=True:
class Author(models.Model):
first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(blank=True)
Тем самым вы сообщили Django, что пустая строка является допустимым значением для адресов электронной почты. По умолчанию для всех полей blank=False, то есть пустые значения недопустимы.
Тут стоит отметить один интересный момент. До сих пор - если не считать метода Unicode () - наши модели выступали в роли определений
таблиц базы данных, по существу аналогами SQL-команды CREATE TABLE на языке Python. Но с добавлением параметра blank=True модель уже перестала быть только определением таблицы. Теперь она содержит более полные сведения о том, чем являются и что могут делать объекты Author. Мы знаем не только, что поле email представлено в базе данных столбцом типа VARCHAR, но и что в некоторых контекстах, например в административном интерфейсе Django, оно необязательно.
Добавив параметр blank=True, перезагрузите форму редактирования информации об авторе (,http://127.0.0A:8000/admin/books/author/add/). Вы увидите, что метка поля - Email - уже не выделена жирным шрифтом. Это означает, что поле необязательное. Теперь можно добавить автора, не указывая адрес электронной почты, и сообщение «This field is required» (Это обязательное поле) не появится.
Как сделать необязательными поля даты и числовые поля
Существует типичная проблема, связанная с добавлением параметра blank=True для полей даты и числовых полей. Но чтобы разобраться в ней, потребуются дополнительные пояснения.
В языке SQL принят свой способ определения пустых значений - специальное значение NULL. Оно означает «неизвестно» или «отсутствует». В языке SQL значение NULL отличается от пустой строки точно так же, как в языке Python объект None отличается от пустой строки "". Следовательно, символьное поле (например, столбец типа VARCHAR) может содержать как NULL, так и пустую строку.
Это может приводить к нежелательной путанице: «Почему в этой записи данное поле содержит NULL, а в той - пустую строку? Между ними есть какая-то разница или данные просто введены неправильно?» Или такой вопрос: «Как получить все записи, в которых поле не заполнено, - искать NULL и пустые строки или только пустые строки?»
Чтобы разрешить эту неоднозначность, Django автоматически генерирует команды CREATE TABLE (см. главу 5) с явной спецификацией NOT NULL в определении каждого столбца. Вот, например, как выглядит сгенерированная команда для модели Author из главы 5:
CREATE TABLE "books_author" (
"id" serial NOT NULL PRIMARY KEY, "first_nane" varchar(30) NOT NULL, "last_nane" varchar(40) NOT NULL, "email" varchar(75) NOT NULL
)
В большинстве случаев такое поведение по умолчанию оптимально для приложения и позволяет забыть о несогласованных данных. К тому же оно прекрасно работает в других частях Django, в частности в административном интерфейсе, где в незаполненные поля записывается пустая строка, а не NULL.
Но для некоторых типов данных, например даты, времени и чисел, пустая строка в качестве значения недопустима. При попытке вставить пустую строку в столбец, содержащий даты или целые числа, вы, скорее всего, получите ошибку базы данных, хотя это и зависит от конкретной СУБД. (PostgreSQL строго контролирует типы данных и в этом случае возбудит исключение; MySQL может принять пустую строку или отвергнуть в зависимости от версии, времени суток и фазы Луны.) В таком случае NULL - единственный способ задать пустое значение. В моделях Django можно сказать, что значения NULL допустимы, добавив в описание поля параметр null=True.
Короче говоря, если вы хотите разрешить пустые значения в числовых полях (например, IntegerField, DecimalField, FloatField) или полях, содержащих дату (например, DateField, TimeField, DateTimeField), то включайте оба параметра null=True и blank=True.
В качестве примера изменим модель Book так, чтобы пустая дата публикации publication_date была допустима. Вот как выглядит модифицированный код:
class Book(models.Model):
title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField(blank=True, null=True)
С добавлением null=True связано больше сложностей, чем с добавлением blank=True, поскольку параметр null=True изменяет семантику базы данных, то есть в команде CREATE TABLE требуется удалить спецификацию NOT NULL из описания столбца publication_date. Чтобы довести модификацию до конца, необходимо обновить базу данных.
По ряду причин Django не пытается автоматизировать изменение схемы базы данных, поэтому вы должны сами выполнить соответствующую команду ALTER TABLE для внесения такого изменения в модель. Напомним, что команда manage, ру dbshell позволяет запустить клиент для используемой СУБД. Вот как можно удалить спецификацию NOT NULL в нашем конкретном случае:
ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;
(Отметим, что этот синтаксис специфичен для СУБД PostgreSQL.) Подробнее изменение схемы базы данных рассматривается в главе 10.
Если теперь вернуться в административный интерфейс, то мы увидим, что форма добавления книги Add Book позволяет оставлять дату публикации пустой.
Изменение меток полей
Метки полей в формах редактирования в административном интерфейсе генерируются исходя из имени поля в модели. Алгоритм прост: Django просто заменяет знаки подчеркивания пробелами и переводит первый символ в верхний регистр. Например, для поля publication_date в модели Book получается метка Publication Date.
Однако имена полей не всегда оказываются удачным выбором для меток полей в форме, поэтому иногда возникает желание изменить сгенерированную метку. Для этого служит параметр verbose_name в описании соответствующего поля модели.
Например, вот как можно поменять метку поля Author.email на e-mail с черточкой:
class Author(nodels.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, verbose_name=’e-mail’)
Выполнив это изменение и перезагрузив сервер, вы увидите, что метка в форме редактирования стала другой.
Отметим, что не следует делать первую букву в значении параметра verbose_name заглавной, если она не должна быть заглавной всегда (как, например, в «USA state»). Django автоматически переводит ее в верхний регистр, когда это требуется, и использует значение, заданное в verbose_name, в тех местах, где заглавные буквы не нужны.
Наконец, отметим, что verbose_name можно передать как позиционный параметр и тем самым слегка сократить запись. В следующем примере делается в точности то же самое, что и выше:
class Author(models.Model):
first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(‘e-mail’, blank=True)
Однако такое решение не годится для полей вида ManyToManyField или ForeignKey, потому что в их описаниях первый аргумент обязательно должен быть классом модели. В таких случаях приходится явно указывать имя параметра verbose_name.
Источник: Головатый А., Каплан-Мосс Дж. Django. Подробное руководство, 2-е издание. - Пер. с англ. - СПб.: Символ- Плюс, 2010. - 560 е., ил.