Django Book: изменение полей на необязательные

Автор: | 20/03/2015

django_logo_2

Предыдущая часть.

После того как вы немного поработаете с панелью управления вы, возможно, заметите некоторые ограничения, например – форма редактирования записи требует, что бы все поля были заполнены, хотя в некоторых случаях вы хотели бы оставить их пустыми. Например, вы хотите что бы поле email модели Authors было не обязательным для заполнения (опциональным).

Что бы указать, что поле email является опциональным – отредактируйте модель Author (которая, как вы должны помнить из предыдущей главы, описана в файле mysite/books/models.py) и добавьте blank=True к полю email, примерно так:

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True)

Это укажет Django, что пустое значение допустимо для поля email у авторов. По умолчанию – у всех полей установлено значение blank=False.

Тут происходит кое-что интересное, на чём стоит остановиться. До сих пор, за исключением метода __unicode__(), наши модели использовались как описания таблиц базы данных в виде Python-выражений для операторов SQL CREATE TABLE. Добавив blank=True мы расширили возможности нашего метода. Теперь класс модели представляет собой более полную коллекцию описаний того, что такое объекты Author и что они могут выполнять.

После того как вы добавили blank=True – перезагрузите страницу “Add author” и вы увидите, что поле Email больше не выделено жирным шрифтом. Теперь вы можете добавить нового автора без указания адреса почты – сообщений “This field is required” больше не будет.

Изменение даты и числовых полей

Описанный пример с blank=True подойдёт и для полей даты и чисел, но тут требуется дополнительное пояснение и действие.

В SQL есть специальный способ для определения пустых значений – это NULLNULL может означать “неизвестно” или “неверное значение”, или другое, в зависимости от приложения.

В SQL значение NULL отличается от пустой строки, так как же специальный объект None в Python отличается от пустой строки (“”). Это значит, что некоторые символьные поля (такие как VARCHAR) могут содержать значения и NULL и пустые строки.

Это может вызвать нежелательную двусмысленность и путаницу: “Почему эта запись имеет значение NULL, а другая – пустую строку?” и “Как мне получить все записи с пустыми значениями – должен ли я искать и NULL и пустые строки, или только пустые строки?

Что бы избежать такой путаницы – сгенерированный Django запрос CREATE TABLE (который мы рассматривали в предыдущей главе) добавляет явное указание NOT NULL для описания каждой колонки. Например, вот запрос для нашей модели Author:

CREATE TABLE `books_author` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `first_name` varchar(30) NOT NULL,
    `last_name` varchar(40) NOT NULL,
    `email` varchar(75) NOT NULL
)
;

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

Однако, имеются исключения, которые касаются полей типа даты, времени и чисел в вашей базе данных – они не принимают пустые строки в качестве корректных значений. Если вы попробуете добавить пустую строку в колонку с датой или цифрами – вы скорее всего получите ошибку базы данных, в зависимости от типа сервера баз данных (PostgreSQL вернёт ошибку, MySQL – может вернуть – а может и нет, в зависимости от используемой версии, времени для и фазы луны). В таком случае – NULL единственный вариант что бы задать пустое значение. В моделях Django вы можете указать, что использование NULL разрешено, добавив строку null=True к нужному полю.

Так вот, если вы хотите разрешить использовать пустые поля для даты (т.е. DateField, TimeField, DateTimeField) или полей с числами (т.е. IntegerField, DecimalField, FloatField) – вам требуется указать и 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)

    def __unicode__(self):
        return self.title

Добавление null=True – более сложный процесс, чем blank=True так как требует изменение синтаксиса базы данных – то есть, оно изменят запрос CREATE TABLE, убирая NOT NULL из описания поля publication_date. Что бы применить это изменение – вам необходимо обновить базу данных.

По многим причинам Django не выполняет изменения в базе автоматически, поэтому вам необходимо выполнить ALTER TABLE самостоятельно, когда вы решите внести такие изменения. Вспомните, что вы можете использовать manage.py dbshell, что бы подключиться к вашей базе из консоли сервера баз данных. Вот как вы можете выполнить ALTER TABLE в данном примере (для MySQL/MariaDB):

MariaDB [django_example1]> ALTER TABLE books_book MODIFY publication_date date;
Query OK, 0 rows affected (0.36 sec)

Или для PostgreSQL:

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

Мы рассмотрим изменения схемы баз данных подробнее далее в нашей книге.

Возвращаясь к панели управления Django – теперь в форме редактирования “Add book” поле даты публикации можно оставлять пустым.

Продолжение – Django Book: изменение заголовков полей