Django中null=True和blank=True有什么区别?
在Django中,当我们添加一个模型字段时,通常会写:
models.CharField(max_length=100, null=True, blank=True)
对于ForeignKey
、DecimalField
等字段也是一样。那么,下面这三种情况有什么基本区别呢:
- 只有
null=True
- 只有
blank=True
- 同时有
null=True
和blank=True
这些设置在不同类型的字段(比如CharField
、ForeignKey
、ManyToManyField
、DateTimeField
)中有什么影响?使用选项1、2或3各自的优缺点是什么呢?
30 个回答
理解Django模型字段定义中的选项非常重要,这些选项至少有两个作用:一是定义数据库表,二是定义模型表单的默认格式和验证。(我说“默认”是因为这些值可以通过提供自定义表单来覆盖。)有些选项影响数据库,有些选项影响表单,还有一些选项同时影响两者。
关于null
和blank
,其他回答已经说明了前者影响数据库表的定义,后者影响模型的验证。我认为通过查看所有四种可能配置的使用案例,可以更清楚地区分它们:
null=False
,blank=False
:这是默认配置,意味着在任何情况下都需要提供值。null=True
,blank=True
:这意味着在任何情况下这个字段都是可选的。不过,如下所述,这并不是推荐的让字符串字段可选的方式。null=False
,blank=True
:这意味着表单不需要值,但数据库需要。有很多使用场景:最常见的用法是可选的字符串字段。正如文档中提到的,Django的惯例是使用空字符串来表示缺失的值。如果同时允许
NULL
,你就会有两种不同的方式来表示缺失的值。(不过如果这个字段还设置了unique
,你就必须使用null=True
来防止多个空字符串导致唯一性检查失败。)另一个常见的情况是你想根据另一个字段的值自动计算一个字段(比如在你的
save()
方法中)。你不希望用户在表单中提供这个值(因此blank=True
),但你希望数据库始终强制提供一个值(null=False
)。还有一种用法是当你想表示一个
ManyToManyField
是可选的。因为这个字段是作为一个单独的表实现的,而不是数据库列,null
是没有意义的。不过,blank
的值仍然会影响表单,控制在没有关系时验证是否成功。
null=True
,blank=False
:这意味着表单需要一个值,但数据库不需要。这可能是最少使用的配置,但也有一些使用场景:
这是ORM在Django 1.8中如何处理blank
和null
字段的方式
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
),而不是必须有值(NOT NULL
)。在 Django 中,像 DateTimeField
或 ForeignKey
这样的字段,如果没有值,就会在数据库里存成 NULL
。
blank
是用来决定这个字段在表单中是否是必填项。这包括后台管理和你自己创建的表单。如果 blank=True
,那么这个字段就不是必填的;如果是 False
,那么这个字段就必须填写。
这两个选项经常一起使用,因为通常如果你允许表单中的某个字段可以留空,那么在数据库中也需要允许这个字段存 NULL
值。唯一的例外是 CharField
和 TextField
,在 Django 中,这两种类型的字段是不会被保存为 NULL
的。留空的值会在数据库中存成一个空字符串(''
)。
举几个例子:
models.DateTimeField(blank=True) # raises IntegrityError if blank
models.DateTimeField(null=True) # NULL allowed, but must be filled out in a form
显然,这两个选项一起用是没有逻辑意义的(不过如果你希望某个字段在表单中始终是必填的,而在通过像 shell 这样的方式处理对象时可以选择性填写,null=True, blank=False
可能会有用)。
models.CharField(blank=True) # No problem, blank is stored as ''
models.CharField(null=True) # NULL allowed, but will never be set as NULL
CHAR
和 TEXT
类型在 Django 中是不会被保存为 NULL
的,所以 null=True
是不必要的。不过,你可以手动把这些字段设置为 None
,这样就会强制将其设置为 NULL
。如果你有这样的需求,还是应该加上 null=True
。