在django中区分null = True,空白= True


901

当我们在Django中添加数据库字段时,通常会这样写:

models.CharField(max_length=100, null=True, blank=True)

同样是与做ForeignKeyDecimalField等有什么根本区别在其

  1. null=True 只要
  2. blank=True 只要
  3. null=Trueblank=True

在相对于不同的(CharFieldForeignKeyManyToManyFieldDateTimeField)字段。使用1/2/3有哪些优点/缺点?




是的,我也有ForeignKey带有blank=True,但没有的用例null=True。保存模型后,我想通过在其中创建已发布的条目来自动“发布”它。所以我无法保存null到数据库,因为每个模型都必须“发布”,但是我希望能够在admin中将该字段留空。
osa 2014年

我认为您可能对[将空的可为空的CharField保存为null而不是空字符串](code.djangoproject.com/ticket/4136感兴趣。关于此的讨论很多,您可能会遇到一个非常实际的问题(例如,您想为每个用户添加一个openid URL,该URL可以为null,并且应该是唯一的)。
ramwin '18

Answers:


1081

null=True在数据库的列中设置NULL(与相对NOT NULL)。Django字段类型(例如DateTimeField或)的空白值ForeignKey将存储NULL在数据库中。

blank确定是否需要表单中的字段。这包括管理员和您的自定义表单。如果blank=True是,则不需要该字段,如果是,则False该字段不能为空。

两者的组合是如此频繁,因为通常如果您要允许表单中的字段为空白,则还需要数据库来允许NULL该字段的值。CharFields和TextFields 是一个例外,在Django中永远不会另存为NULL。空值作为空字符串('')存储在DB中。

一些例子:

models.DateTimeField(blank=True) # raises IntegrityError if blank

models.DateTimeField(null=True) # NULL allowed, but must be filled out in a form

显然,这两个选项在使用上没有逻辑意义(尽管null=True, blank=False如果您希望始终以表单形式要求字段,则可能会有用例,当通过诸如Shell之类的对象处理对象时,这是可选的。)

models.CharField(blank=True) # No problem, blank is stored as ''

models.CharField(null=True) # NULL allowed, but will never be set as NULL

CHARTEXT类型永远不会NULL被Django 保存,因此null=True没有必要。但是,您可以手动设置这些字段之一None以强制将其设置为NULL。如果您有可能需要这样做的情况,则仍应包括null=True


8
IntegrityError当Django尝试将记录保存到数据库时引发。用户不需要填写该字段,这就是问题所在,因为在数据库级别它不是null。
克里斯·普拉特

5
否,克里斯试图指出为什么空白= True而没有null = True会导致DateTimeField中出现问题。
Vinod Kurup

4
对Oracle用户的注意:“ CHARTEXT永远不会NULL由Django 保存为”是不正确的。对于大多数后端来说都是如此,但是Oracle会将空字符串强制为NULL,因此Django Oracle后端是上述声明Django Docs
stv 2016年

10
@ChrisPratt对您的帖子进行较小的更正:如果将null设置为True,则CharFields 可以在数据库中保存为NULL(None在Python中转换为)。该文档甚至可以说,以避免设置空=真,因为它允许两种不同的“blanky”的价值观。我只是测试这种行为与Django的1.8 / MySQL的5.6
爱德华杜泽

3
是没有人要提到的组合:blank=Truenull=Falsedefault="something"
Brian H.

124

这是Django 1.8 的ORM映射blanknull字段的方式

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
)

41
换句话说,blank对数据库没有影响,并null控制数据库列是否允许NULL值。这个答案是很长的话,并且不提供有关的任何有用信息blank
卡尔·梅耶

19
@CarlMeyer:我想看看它如何映射到数据库并共享,因为这样可以节省其他人的时间。在吸收和致力于记忆方面,理论与范例会有所不同。实际上,我不愿意为未使用的数据库添加映射。谢谢你的反对。认为有用的人的数量显然与您不同意。
用户

5
如果您从呈现的数据中得出一些总结性结论,这可能是一个有用的答案,但是我认为呈现原始数据转储不是一个有用的答案。在这种情况下,它实际上是一个误导性的答案,因为(没有进一步的评论),它意味着两者的效果blanknull应该体现在数据库列,而实际上blank只影响Python的处理,而不是数据库列。如果其他人觉得有用,则可以自由投票;对于被误导性答案误导的人,也有可能认为它很有用。
卡尔·梅耶

4
被接受的答案将近3年了,详细解释了所有内容。在这里重复相同的信息没有意义。
用户

48

如Django模型字段参考中所述:链接

栏位选项

以下参数可用于所有字段类型。所有都是可选的。


null

Field.null

如果为True,则Django将NULL在数据库中存储空值。默认值为False

避免null在基于字符串的字段(例如CharField和)上使用, TextField因为空字符串值将始终存储为空字符串,而不是NULL。如果基于字符串的字段具有null=True,则表示它具有两个“无数据”的可能值:NULL和空字符串。在大多数情况下,为“无数据”设置两个可能的值是多余的。Django约定是使用空字符串,而不是 NULL

对于基于字符串的字段和基于非字符串的字段,blank=True如果您希望允许表单中的空值,还需要进行设置,因为该null参数仅影响数据库存储(请参阅参考资料blank)。

注意

使用Oracle数据库后端时,无论此属性如何,都将存储值NULL表示空字符串


blank

Field.blank

如果为True,则该字段允许为空白。默认值为False

请注意,这与有所不同nullnull与数据库完全相关,而blank与验证相关。如果字段包含blank=True,则表单验证将允许输入一个空值。如果字段包含blank=False,则将需要该字段。


46

理解Django模型字段定义中的选项至少有两个作用是至关重要的:定义数据库表,定义默认格式和验证模型形式。(我之所以说“默认值”,是因为可以始终通过提供自定义表单来覆盖这些值。)某些选项影响数据库,某些选项影响表单,而某些选项同时影响这两种形式。

关于nullblank,其他答案已经明确表明,前者影响数据库表定义,而后者影响模型验证。我认为,通过查看所有四种可能配置的用例,可以使区分更加清楚:

  • null=Falseblank=False:这是默认的配置和手段,该值在所有情况下需要。

  • null=Trueblank=True:表示该字段在所有情况下都是可选的。(但是,如下所述,这不是使基于字符串的字段为可选的推荐方法。)

  • null=Falseblank=True:表示表单不需要值,但是数据库需要。有许多用例:

    • 最常见的用法是用于基于字符串的可选字段。如文档中所述,Django习惯用法是使用空字符串表示缺少的值。如果NULL还允许,您将最终以两种不同的方式指示缺失值。

    • 另一种常见情况是,您想根据另一个字段的值自动计算一个字段(例如,使用您的save()方法)。您不希望用户以某种形式提供值(因此blank=True),但是您希望数据库强制始终提供值(null=False)。

    • 另一个用途是当您想要指示a ManyToManyField是可选的时。因为此字段是作为单独的表而不是数据库列实现的,null所以没有意义blank不过,的值仍会影响表单,控制在没有关系时验证是否成功。

  • null=Trueblank=False:表示表单需要一个值,但数据库不需要。这可能是最不常用的配置,但是有一些用例:

    • 要求用户始终包含一个值是完全合理的,即使您的业务逻辑实际上并不需要它也是如此。毕竟,表单只是添加和编辑数据的一种方式。您可能拥有的代码生成的数据不需要与人工编辑器一样严格的验证。

    • 我看到的另一个用例是当你有一个ForeignKey你不想允许级联删除的情况。也就是说,在正常使用中,该关系应始终存在(blank=False),但是如果它指向的对象恰好被删除,则您也不想删除该对象。在这种情况下,您可以使用null=Trueon_delete=models.SET_NULL实现一种简单的软删除


1
这是一个完美的答案,所有可能的组合都以非常简洁的方式进行了说明!
俄罗斯

1
应该是公认的答案。
Tom Mac

28

您可能有答案,但是直到今天,仍然很难判断是否将null = True或blank = True或两者都放在一个字段中。我个人认为为开发人员提供这么多的选择是非常无用的,而且令人困惑。让句柄根据需要为空或空格。

我遵循这张表,来自Django的两个独家新闻在此处输入图片说明

该表显示了何时对每种字段类型使用null或空白


26

简单null=True定义数据库应该接受NULL值,另一方面,blank=True在表单验证中定义此字段是否应该接受空白值(如果blank=True它接受该字段中没有值的表单,并且blank=False在表单验证中为[默认值],它将显示此字段为必填错误。

null=True/False 与数据库有关

blank=True/False 与表单验证有关


11

这是带有blank= True和的字段的示例null=True

description = models.TextField(blank = True,null = True)

在这种情况下:: blank = True告诉我们的表格可以将描述字段留空

null = True:告诉我们的数据库可以在db字段中记录一个空值并且不给出错误。


7

这里,是的主要区别null=Trueblank=True

两者的默认值nullblank值为False。这两个值都在字段级别起作用,即我们是否要保留字段nullblank

null=True将字段的值设置为NULL即无数据。它基本上是针对数据库列的值。

date = models.DateTimeField(null=True)

blank=True确定是否需要表单中的字段。这包括管理员和您自己的自定义表单。

title = models.CharField(blank=True) // title can be kept blank. 在数据库("")中将被存储。 null=True blank=True这意味着该字段在所有情况下都是可选的。

epic = models.ForeignKey(null=True, blank=True)
// The exception is CharFields() and TextFields(), which in Django are never saved as NULL. Blank values a

6
null = True

意味着对于要填充的字段没有数据库的约束,因此您可以拥有一个具有空值的对象,该对象具有此选项。

blank = True

意味着没有django形式的验证约束。因此,当您modelForm为此模型填写时,可以不填写此选项。


6

null和blank的默认值为False。

空:与数据库有关。定义给定的数据库列是否将接受空值。

空白:与验证相关。调用form.is_valid()时,将在表单验证期间使用它。

话虽这么说,具有null = True和blank = False的字段是完全可以的。在数据库级别上,该字段可以为NULL,但是在应用程序级别上,它是必填字段。

现在,大多数开发人员都将其弄错了:为基于字符串的字段(如CharField和TextField)定义null = True。避免这样做。否则,您最终将获得两个可能的“无数据”值,即:和空字符串。为“无数据”设置两个可能的值是多余的。Django约定是使用空字符串,而不是NULL。


5

当我们在Django admin中保存任何内容时,将在Django级别和数据库级别进行两步验证。我们无法在数字字段中保存文本。

数据库的数据类型为NULL,没什么。当Django在数据库中创建列时,它指定它们不能为空。而且,如果您尝试保存NULL,则会出现数据库错误。

同样在Django-Admin级别,默认情况下所有字段都是必填字段,您无法保存空白字段,Django会抛出错误。

因此,如果要保存空白字段,则需要在Django和数据库级别允许它。blank = True-将允许管理面板中的空字段null = True-将允许将NULL保存到数据库列。


5

有一点null=True甚至在CharField或上也有必要TextField,那就是数据库unique为列设置了标志。

换句话说,如果您在Django中具有唯一的Char / TextField,则需要使用以下代码:

models.CharField(blank=True, null=True, unique=True)

对于非唯一的CharField或TextField,最好跳过null=True一些,否则某些字段将被设置为NULL,而另一些字段将被设置为“”,并且您每次都必须检查字段值是否为NULL。


3

是数据库和空白是字段的验证要显示在文本框一样的用户界面得到的人的姓氏。如果lastname = models.charfield(blank = true),则没有要求用户输入姓氏,因为这是可选字段。如果lastname = models.charfield(null = true), 则意味着如果该字段未从用户那里获取任何值,则它将作为空字符串“”存储在数据库中。


1

模型中null = True和blank = True的含义还取决于如何在表单类中定义这些字段。

假设您定义了以下类:

class Client (models.Model):
    name = models.CharField (max_length=100, blank=True)
    address = models.CharField (max_length=100, blank=False)

如果表单类的定义如下:

class ClientForm (ModelForm):
    class Meta:
        model = Client
        fields = ['name', 'address']
        widgets = {
            'name': forms.TextInput (attrs = {'class': 'form-control form-control-sm'}),
            'address': forms.TextInput (attrs = {'class': 'form-control form-control-sm'})
        }

然后,“名称”字段将不是强制性的(由于模型中的blank = True),而“地址”字段将是强制性的(由于模型中的blank = False)。

但是,如果已经这样定义ClientForm类:

class ClientForm (ModelForm):
    class Meta:
        model = Client
        fields = ['name', 'address']

    name = forms.CharField (
        widget = forms.TextInput (attrs = {'class': 'form-control form-control-sm'}),
    )
    address = forms.CharField (
        widget = forms.TextInput (attrs = {'class': 'form-control form-control-sm'}),
    )

然后,两个字段(“名称”和“地址”)都是必填字段“因为以声明方式定义的字段保持原样”https://docs.djangoproject.com/zh/3.0/topics/forms/modelforms/) ,即表单字段的'required'属性的默认值为True,即使在模型中将该字段设置为blank = True,这也将要求填写字段'name'和'address'。



0

下表说明了主要区别:

+--------------------------------------------------------------------+
| Purpose                  | null=True        | blank = True         |
|--------------------------|------------------|----------------------|
| Field can be empty in DB | Do this          | Unaffected           |
|--------------------------|------------------|----------------------|
| ModelForm(required field)| Unaffected       | field not required   |
|--------------------------|------------------|----------------------|
| Form Validation          | Unaffected       | field not required   |
|--------------------------|------------------|----------------------|
| on_delete=SET_NULL       | Need this        | Unaffected           |
+--------------------------------------------------------------------+

0

在很简单的话

空白不同于空值。

纯粹数据库相关的,而空白是验证相关的(在形式所需)

如果是null=True,Django会的store empty values as NULL in the database。如果有一个字段blank=True,则将进行表单验证allow entry of an empty value。如果字段的空白为False,则将需要该字段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.