问题 Django ORM,CharField和blank = True


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感到愤怒。

谢谢!


10625
2017-08-18 17:31


起源



答案:


通常情况下看似棘手的问题,手头的问题是用户错误。

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

这反过来导致了 IntegrityError 的问题。 Django不知道 phone_number 场,所以即使我已经设定 blank=True,Django没有努力插入一个空值 - 而数据库当然认为这意味着NULL。

这导致一系列不同的跟踪错误,包括上述错误。

令人惊讶的是,这些棘手的问题往往是由于愚蠢的小错误引起的 - 就像我2个月前写的部署脚本而忘记更新。

感谢阅读人们,我已经提出了其他答案,但我需要接受我的,因为它最终是解决方案。


7
2017-08-21 19:32





我发现如果你明确地将字段值设置为 None 你仍然会得到这些错误。换句话说 default= 只要你创建了python对象,就会应用这个东西,而不是当你将它保存到数据库时。

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


6
2017-09-24 18:18



如果你通过了同样的事情似乎也会发生 None 到构造函数(所以,在创建时) - Tim Tisdall


答案:


通常情况下看似棘手的问题,手头的问题是用户错误。

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

这反过来导致了 IntegrityError 的问题。 Django不知道 phone_number 场,所以即使我已经设定 blank=True,Django没有努力插入一个空值 - 而数据库当然认为这意味着NULL。

这导致一系列不同的跟踪错误,包括上述错误。

令人惊讶的是,这些棘手的问题往往是由于愚蠢的小错误引起的 - 就像我2个月前写的部署脚本而忘记更新。

感谢阅读人们,我已经提出了其他答案,但我需要接受我的,因为它最终是解决方案。


7
2017-08-21 19:32





我发现如果你明确地将字段值设置为 None 你仍然会得到这些错误。换句话说 default= 只要你创建了python对象,就会应用这个东西,而不是当你将它保存到数据库时。

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


6
2017-09-24 18:18



如果你通过了同样的事情似乎也会发生 None 到构造函数(所以,在创建时) - Tim Tisdall