Django ORM、CharField 和空白=True

Posted

技术标签:

【中文标题】Django ORM、CharField 和空白=True【英文标题】:Django ORM, CharField and blank=True 【发布时间】:2011-10-30 00:11:57 【问题描述】:

Django 的文档非常清楚地将空字符串存储为“”,而不是在数据库级别存储为 NULL(因此空数据只有一种可能的格式):

请注意,空字符串值将始终存储为空字符串,而不是 NULL。仅对非字符串字段(例如整数、布尔值和日期)使用 null=True。对于这两种类型的字段,如果您希望在表单中允许空值,您还需要设置 blank=True,因为 null 参数只影响数据库存储(请参阅空白)。

不过,在添加新字段后,我开始在新字段 (phone_number) 上遇到 IntegrityErrors。

“phone_number”列中的空值违反非空约束

该模型在新字段中看起来像这样(我执行了南迁移):

class Person(models.Model):
    user = models.ForeignKey(User)
    description = models.TextField(blank=True)
    phone_number = models.CharField(blank=True)

我已经(暂时)通过在 phone_number 上设置 null=True 解决了这个问题,但现在我的数据库中有数百个带有空字符串的条目和一个 NULL 值。 (我也尝试将 default='' 添加到 phone_number 字段,但我仍然看到 IntegrityError 问题。)

过去我一直使用 mysql,但在这个项目中我使用的是 Postgres。生成的 SQL 插入尝试是:

'INSERT INTO "people_person" ("user_id", "description", "gender", "birthdate", "default_image_id", "zip_code", "beta_status") VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING "people_person"."id"'.

我的期望是 Django 会在“phone_number”列中插入一个空白字符串,但它似乎没有这样做。我可能期望的另一件事是 Django 在 CREATE TABLE 语句中包含一个 SET DEFAULT,但它没有。所以 Postgres 对那一列的 NOT NULL 很生气。

谢谢!

【问题讨论】:

【参考方案1】:

与看似难以解决的问题一样,手头的问题是用户错误。

我的应用程序有两个入口点 - 两个 WSGI 文件,但只有一个代码库。通常,Apache 只会在文件被触摸时重新加载您的代码。我的部署脚本只涉及其中一个 WSGI 文件——这意味着通过另一个 WSGI 文件访问我的站点的人仍然看到旧代码。更糟糕的是,数据库是在旧代码下修改的,但模型还是和以前一样。

这反过来又导致了IntegrityError 问题。 Django 不知道phone_number 字段,所以即使我设置了blank=True,Django 也没有努力插入一个空白值——数据库当然认为这意味着NULL。

这导致了一系列不同的追踪错误,包括上面的错误。

令人惊讶的是,此类真正棘手的问题经常是由愚蠢的小疏忽引起的——比如我在 2 个月前编写的部署脚本忘记更新。

感谢大家阅读,我对其他答案投了赞成票,但我需要接受我的答案,因为它最终是解决方案。

【讨论】:

【参考方案2】:

我发现,如果您将字段值显式设置为None,您仍然会收到这些错误。换句话说,default= 是在您创建 python 对象后立即应用的,而不是在您将其保存到数据库时。

我想这是合理的,但有点出乎意料。

【讨论】:

如果您将None 传递给构造函数(因此,在创建时),似乎会发生同样的事情

以上是关于Django ORM、CharField 和空白=True的主要内容,如果未能解决你的问题,请参考以下文章

为啥 django.forms.CharField 中缺少“空白”,但在 django.db.models.CharField 中存在?

Django 1.7 空白 CharField/TextField 约定

django ORM 一对多, 多对多 查询 以及 结合Tamplate

django orm

django ORM的外键操作

左加入 Django ORM