В чем разница между null=True и blank=True в Django?
Проблема с использованием параметров null
и blank
в моделях Django
Когда мы добавляем поле модели в Django, мы обычно используем такой синтаксис:
models.CharField(max_length=100, null=True, blank=True)
Аналогичным образом применяются и другие типы полей, такие как ForeignKey
, DecimalField
и т.д.
Меня интересует, в чем основное различие между следующими вариантами использования параметров:
null=True
толькоblank=True
толькоnull=True
иblank=True
Как эти параметры влияют на различные типы полей (например, CharField
, ForeignKey
, ManyToManyField
, DateTimeField
)? Хочу понять преимущества и недостатки выбора каждого из этих вариантов.
Буду признателен за разъяснения и примеры использования, которые помогут прояснить эту тему!
5 ответ(ов)
null=True
устанавливает в вашей базе данных значение NULL
(в отличие от NOT NULL
) для столбца. Пустые значения для таких типов полей Django, как DateTimeField
или ForeignKey
, будут храниться в базе данных как NULL
.
Параметр blank
определяет, будет ли поле обязательным в формах. Это касается как админки, так и ваших пользовательских форм. Если blank=True
, то поле не будет обязательным, в то время как если False
, поле не может быть пустым.
Комбинация этих двух параметров встречается часто, потому что, как правило, если вы собираетесь разрешить полю быть пустым в вашей форме, вам также нужно, чтобы ваша база данных позволяла значения NULL
для этого поля. Исключением являются CharField
и TextField
, которые в Django никогда не сохраняются как NULL
. Пустые значения хранятся в базе данных как пустая строка (''
).
Несколько примеров:
models.DateTimeField(blank=True) # вызывает IntegrityError, если пустое
models.DateTimeField(null=True) # NULL разрешен, но должен быть заполнен в форме
Очевидно, что эти два параметра не имеют смысла использовать вместе (хотя может быть и случай использования null=True, blank=False
, если вы хотите, чтобы поле всегда было обязательным в формах, но опциональным при работе с объектом, например, в консоли).
models.CharField(blank=True) # Все в порядке, пустое хранится как ''
models.CharField(null=True) # NULL разрешен, но никогда не будет установлен как NULL
Типы CHAR
и TEXT
никогда не сохраняются как NULL
в Django, поэтому null=True
не нужен. Однако вы можете вручную установить одно из этих полей в None
, чтобы заставить его сохранить как NULL
. Если у вас есть сценарий, где это может быть необходимо, все же стоит указать null=True
.
В Django 1.8 ORM обрабатывает поля blank
и null
следующим образом:
Для класса модели Test
, определённого как:
class Test(models.Model):
charNull = models.CharField(max_length=10, null=True)
charBlank = models.CharField(max_length=10, blank=True)
charNullBlank = models.CharField(max_length=10, null=True, blank=True)
intNull = models.IntegerField(null=True)
intBlank = models.IntegerField(blank=True)
intNullBlank = models.IntegerField(null=True, blank=True)
dateNull = models.DateTimeField(null=True)
dateBlank = models.DateTimeField(blank=True)
dateNullBlank = models.DateTimeField(null=True, blank=True)
При создании базы данных для PostgreSQL 9.4 соответствующие поля будут следующими:
CREATE TABLE Test (
id serial NOT NULL,
"charNull" character varying(10),
"charBlank" character varying(10) NOT NULL,
"charNullBlank" character varying(10),
"intNull" integer,
"intBlank" integer NOT NULL,
"intNullBlank" integer,
"dateNull" timestamp with time zone,
"dateBlank" timestamp with time zone NOT NULL,
"dateNullBlank" timestamp with time zone,
CONSTRAINT Test_pkey PRIMARY KEY (id)
)
А для MySQL 5.6 создаваемые поля будут выглядеть так:
CREATE TABLE Test (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`charNull` VARCHAR(10) NULL DEFAULT NULL,
`charBlank` VARCHAR(10) NOT NULL,
`charNullBlank` VARCHAR(10) NULL DEFAULT NULL,
`intNull` INT(11) NULL DEFAULT NULL,
`intBlank` INT(11) NOT NULL,
`intNullBlank` INT(11) NULL DEFAULT NULL,
`dateNull` DATETIME NULL DEFAULT NULL,
`dateBlank` DATETIME NOT NULL,
`dateNullBlank` DATETIME NULL DEFAULT NULL
)
Обратите внимание, что:
- Поле с
null=True
может хранить значение NULL в базе данных. - Поле с
blank=True
не требует заполнения при валидации форм Django, что делает его не обязательным к заполнению на уровне приложения. - В PostgreSQL поля, где задан только
blank=True
, по умолчанию будут созданы какNOT NULL
. - В MySQL также будут установлены аналогичные ограничения.
В Django null=True
и blank=True
имеют разные назначения и используются в разных контекстах.
null=True
определяет, что поле в базе данных может принимать значениеNULL
. Это означает, что при сохранении записи в базе данных, это поле может быть пустым (не заданным).blank=True
связано с валидацией форм. Еслиblank=True
, это означает, что поле может быть оставлено пустым при отправке формы. В случае еслиblank=False
(значение по умолчанию), при валидации формы будет выдана ошибка This field is required, если поле не было заполнено.
Итак, можно выделить ключевые различия:
null=True/False
относится к базе данных.blank=True/False
относится к валидации форм.
Обратите внимание, что для поля, которое может быть NULL
в базе данных и пустым в форме, необходимо устанавливать оба атрибута: null=True
и blank=True
.
Пример поля с параметрами blank=True
и null=True
в Django:
description = models.TextField(blank=True, null=True)
В данном случае:
blank=True
: указывает нашей форме, что поле описания может быть оставлено пустым (необязательным для заполнения).null=True
: сообщает нашей базе данных, что допустимо записывать значениеnull
в это поле, что предотвратит возникновение ошибки при сохранении данных.
Если вы установите null=True
, это позволит значению столбца вашей базы данных быть равным NULL
. Если же вы установите только blank=True
, Django установит значение по умолчанию для столбца как ""
.
Существует один случай, когда null=True
будет необходим даже для CharField
или TextField
, и это когда для столбца установлен флаг unique
. В этом случае вам нужно будет использовать:
a_unique_string = models.CharField(blank=True, null=True, unique=True)
Рекомендуется избегать использования null=True
для неуникальных CharField
или TextField
. В противном случае некоторые поля будут установлены как NULL
, в то время как другие – как ""
, и вам придется каждый раз проверять значение поля на NULL
.
Как выполнить фильтрацию запросов в Django по условию "не равно"?
Существует ли список временных зон Pytz?
Превысил ли Django 100 тыс. посещений в день? [закрыто]
Почему используется string.join(list), а не list.join(string)?
Создание словаря с помощью генератора словарей