在Django中,null=True和blank=True有什么区别?

1364

当我们在Django中添加模型字段时,通常会写成:

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

对于ForeignKeyDecimalField等字段也是如此操作。以下是关于在不同的(CharField, ForeignKey, ManyToManyField, DateTimeField)字段中应用:

  1. null=True仅针对
  2. blank=True仅针对
  3. null=Trueblank=True

有什么区别?使用选项1、2或3的优点和缺点是什么?


20
这里有关于这个问题的好回答:https://dev59.com/tWsz5IYBdhLWcg3wBzbi 和 https://dev59.com/_2855IYBdhLWcg3wXTAI。 - juliomalegria
6
好的阅读材料:http://www.b-list.org/weblog/2006/jun/28/django-tips-difference-between-blank-and-null/这篇文章讨论了在Django模型中使用"blank"和"null"选项的区别。简单来说,"blank"是用于验证表单数据的,而"null"是用于数据库存储的。如果一个字段可以为空,则应该将"blank"设置为True,并且如果该字段与数据库的NULL值相关联,则应该将"null"设置为True。此外,作者还讨论了一些关于如何正确使用这些选项的技巧和陷阱。 - salmatron
是的,我也有这样一个ForeignKey的应用场景,其中blank=True,但没有null=True。当保存模型时,我想通过创建已发布的条目来自动“发布”它。因此,我不能将null保存到数据库中,因为每个模型都必须是"published",但我希望能够在管理页面中留空该字段。 - Sergey Orshanskiy
1
我认为你可能会对将空的可空CharField保存为null而不是空字符串感兴趣。关于这个问题有很多讨论,你可能会遇到一个非常实际的问题(例如,你想为每个用户添加一个可以为空且应该是唯一的openid url)。 - ramwin
避免在CharField和TextField等基于字符串的字段上使用null。https://docs.djangoproject.com/en/3.1/ref/models/fields/ - Fernando Valente
28个回答

1
根据文档,null 是与数据库相关的。如果 null=true,则 DB 将 null 输入存储为 null。否则,空字符串存储为空字符串。 而如果 blank=true,则表单将验证其是否为 ok,否则该字段将被表单视为“必填”。
两者默认都是 false。

即使 null=False,您仍然可以在 CharField 中存储空字符串 ('')。如果 null=True,则可以存储 None 值或空字符串 ''。 - Waldemar Podsiadło

1

blank=True可以被设置在任何一个模型字段上,用于控制在表单中输入值时是否允许该字段为空。这里我们谈论的是输入数据。

null=True,如果我们为一个字段设置了blank=True,并且该模型字段没有接收到任何值,那么当数据写入数据库时,数据库或Django需要对该字段进行处理。对于任何文本内容,空字符串将被存储在数据库中,因此数据库中存储了一个值。对于其他类型的字段,如日期字段或数字字段,我们使用特殊的数据类型“null”。如果一个字段可能没有值,可以使用“null”,但默认情况下,Django不允许“null”值。这就是为什么需要明确设置null=True的原因。

假设你为任何非文本字段设置了blank=True,但没有指定“null=True”,Django将不知道要存储什么,并会抛出错误。


1

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,'name'字段将不再是必填项,而'address'字段将成为必填项,因此必须填写。

然而,如果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'}),
    )

然后,两个字段('name'和'address')将是必填的,因为声明定义的字段保持不变https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/),即表单字段的'required'属性的默认值为True,这将要求填写字段'name'和'address',即使在模型中,该字段已设置为blank=True。


1
这张表格展示了主要的区别:
+--------------------------------------------------------------------+
| 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时,如果字段未填写,它将在数据库中设置为null。如果你设置blank=true,则不会给字段设置任何值。

0

当你说null=False时,它意味着必须将数据传递到数据库以保存。当你说blank=False时,它意味着必须从前端输入数据,反之亦然。


0

每个Django模型中的选项有两个用途

  1. 在数据库层面上定义字段约束(如SQL、Postgresql或其他任何数据库)
  2. 在表单层面上定义字段约束(在数据库层级之上的框架层面上)

现在让我们回到nullblank

  • blank与Django表单相关。它用于验证Django表单,无论是在管理系统还是在Django中。尤其是当我们调用form.is_valid()时。
  • null与数据库相关。它告诉底层数据库是否允许保存null值。

例如,让我们看下面的例子-

class Company(models.Model):
    name = models.CharField(max_length=100)
    website = models.UrlField()
    founded_on = models.DateField(blank=True, null=False)
    random_date = models.DateFeild(blank=False, null=True)
    random_text = models.TextField(null=True, blank=True)

我定义了一个Company模型,其中有2个字段,我们正在尝试使用blanknull选项。让我们看看不同字段会发生什么。

  • founded_on:在表单级别(框架/语言级别)可以接收空的string值。保存到数据库时,如果该值为null,则会引发IntegrityError异常,因为数据库不接受null值,此时null值是false

  • random_date:在表单级别(框架)通过验证错误接收空值,因为空白不允许,这是在表单级别设置的blank=True约束。但是,在数据库层面,该列也允许为空值。

  • random_text:这个选项意味着该字段允许在数据库层面被保存为null,并且根据Django表单验证逻辑,允许空的string值作为有效数据,因为blank=True。简而言之,在框架级别可以接收空值,在数据库级别可以存储空值。

要解决所有这些混淆,请将您的数据库提交视为两层过程。

  • 首先,填写表单,在框架级别调用验证数据。
  • 其次,它具有数据库级别选项,有助于定义DB约束。

这里blank是框架级别的东西,而null是数据库级别的约束。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接