为什么Django中的空字符字段被读为None而不是空字符串?

0 投票
2 回答
2000 浏览
提问于 2025-04-17 06:46

我有一个模型,像这样:

class Item(models.Model):
    text = model.CharField(max_length=50)
    extra_text = model.CharField(max_length=50, blank=True)

假设我有一个对象实例,其中的 extra_text 是空的,所以在数据库里它被存储为一个空字符串 ''

我读取这个对象,比如:

myitem = Item.objects.get(id=1)

现在我检查 myitem.extra_text 的值,发现它不是 '',而是 None(在 IPython shell 里):

In [36]: myitem.extra_text == ''
Out[36]: False

In [37]: myitem.extra_text == None
Out[37]: True

In [38]: myitem.extra_text is None
Out[38]: True

难道此时它不应该是 '' 吗?在数据库里它是 '',因为不允许为 NULL

我的问题是,这样的对象不能不做修改地保存回数据库,因为如果我尝试这样做,我会得到:

In [39]: myitem.save()
<skipping Traceback>
IntegrityError: null value in column "extra_text" violates not-null constraint

我觉得很奇怪,我刚从数据库读取的对象实例,明明没有做任何修改,却不能保存回数据库。我是不是做错了什么?解决这个问题的正确方法是什么?

2 个回答

0

我只能想到一个可能出现这种情况的场景:

你有一个已经存在的模型,数据库里也有一些数据。然后你新增了一个字符字段(CharField),但忘了给现有的数据设置一个默认值。当你查询这些已有的数据时,这个字符字段就没有值,但又不允许为空,这样就会出现完整性错误。

如果这听起来很熟悉,你可以通过在添加字段时指定一个默认值(即使只是'')来解决这个问题。

0

我找到了问题所在:我在这个模型的这个字段上使用了 django-modeltranslation,我原本以为它只会影响模板,认为在模板外部,item.extra_text 还是会和数据库里的 extra_text 列关联。但实际上,即使在命令行中,它也会使用本地化的(转换成默认语言的)extra_text_en 列,而这个列的值是 NULL。

现在我已经把数据库中所有行的 extra_text 字段更新为 '',并且设置为 NOT NULL DEFAULT '',这样当我在 Python 中读取时,它的值是 u''。但是问题是,django-modeltranslation 仍然想把它保存为 NULL,这就导致了 IntegrityError: null value in column "title_extra_en" violates not-null constraint 的错误。

所以我还是不知道怎么让它和 django-modeltranslation 一起正常工作。

撰写回答