Django CharField 不默认为空字符串

Posted

技术标签:

【中文标题】Django CharField 不默认为空字符串【英文标题】:Django CharField not defaulting to empty string 【发布时间】:2015-06-03 20:53:04 【问题描述】:

Django 文档说:

避免在基于字符串的字段(例如 CharField 和 TextField 因为空字符串值将始终存储为空 字符串,而不是 NULL。

所以我像这样设置我的模型

class Address(models.Model):
    address_num = models.TextField()
    street_predir = models.CharField(max_length=2, default='')    # optional
    street_name = models.TextField()
    street_suffix = models.CharField(max_length=4, default='')    # optional
    street_postdir = models.CharField(max_length=2, default='')   # optional

然后创建一个缺少可选字段的对象

raw_address = '1234 MAIN ST'
# Run this through an address parser - this returns a dictionary of address components
# Optional fields are returned as None if not present
components = parser.parse(raw_address)
address = Address(**components)
address.save()

但我得到了错误

null value in column "street_predir" violates not-null constraint
DETAIL:  Failing row contains (8633570, 2057 ANCHOR ST, 2057, null, ANCHOR, ST, null, null, null, ANCHOR ST, null, null, )

谁能解释为什么这不默认为空字符串? FWIW 我正在使用 Django 1.7.4 和 Postgres DB。

【问题讨论】:

不需要default='',您应该使用blank=True 来允许表单中的空值。您能否发布回溯以及from django.db import connection; print(connection.queries) 的内容? 您能否发布创建对象的代码或任何自定义保存方法?在某处,您明确设置 None 而不是空字符串。 “... 将始终存储为空字符串,而不是 NULL”部分似乎不再存在:code.djangoproject.com/ticket/4136#comment:42 【参考方案1】:
# Run this through an address parser - this returns a dictionary of address components
# Optional fields are returned as None if not present
components = parser.parse(raw_address)

这显式地将值设置为None,在数据库中直接转换为NULL。您应该删除所有具有值 None 的键,或者将值替换为 ''

components = k: v for k, v in components.items() if v is not None

这只会设置非空组件,其他的将默认为空字符串而不是NULL

【讨论】:

【参考方案2】:

在您粘贴的引用文本中,稍稍声明:

如果您希望在表单中允许空值,您还需要设置 blank=True,因为 null 参数只影响数据库存储(请参阅空白)。

对于字符串,您应该使用blank=True

class MyModel(models.Model):
    required_string = models.CharField()
    optional_string = models.CharField(blank=True, default="")

【讨论】:

我没有使用任何表单或管理站点——这都是通过代码实现的。我尝试设置blank=True,但我仍然得到相同的“违反非空约束”:/ 别忘了null=True @C.B. “避免在基于字符串的字段(例如 CharField 和 TextField)上使用 null。如果基于字符串的字段具有 null=True,则意味着它有两个可能的“无数据”值:NULL 和空字符串。在大多数情况下, “没有数据”有两个可能的值是多余的; Django 约定是使用空字符串,而不是 NULL。" - docs.djangoproject.com/en/1.11/ref/models/fields/#null

以上是关于Django CharField 不默认为空字符串的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM、CharField 和空白=True

Django ORM、CharField 和空白=True

关于Django字段类型中 blank和null的区别

没有空字符串的 Django CharField

Django:仅使用 annotate() 和 values() 计算非空 CharField

Django:查找非空字符串的优雅方式