在Django中允许为空的唯一字段

我有Foo模型,其中有栏杆。bar字段应该是唯一的,但允许为空,这意味着如果bar字段为null,我想允许多个记录,但如果不是,null则值必须是唯一的。

这是我的模型:

class Foo(models.Model):

name = models.CharField(max_length=40)

bar = models.CharField(max_length=40, unique=True, blank=True, null=True, default=None)

这是该表的相应SQL:

CREATE TABLE appl_foo

(

id serial NOT NULL,

"name" character varying(40) NOT NULL,

bar character varying(40),

CONSTRAINT appl_foo_pkey PRIMARY KEY (id),

CONSTRAINT appl_foo_bar_key UNIQUE (bar)

)

当使用管理界面在bar为null的情况下创建多个1个foo对象时,它给我一个错误:“此Bar的Foo已经存在。”

但是,当我插入数据库(PostgreSQL)时:

insert into appl_foo ("name", bar) values ('test1', null)

insert into appl_foo ("name", bar) values ('test2', null)

这样做很好,它允许我插入1条以上且bar为null的记录,因此数据库允许我执行我想要的操作,这是Django模型的错误。有任何想法吗?

编辑

就数据库而言,解决方案的可移植性不是问题,我们对Postgres感到满意。我尝试过设置可调用对象的唯一性,这是我的函数针对bar的特定值返回True / False ,它没有给出任何错误,但是接缝就像根本没有任何作用。

到目前为止,我已经从bar属性中删除了唯一的说明符,并在应用程序中处理了bar的唯一性,但是仍在寻找更优雅的解决方案。有什么建议吗?

回答:

自从票务#9039被修复以来,Django就唯一性检查的目的没有将NULL视为NULL,请参阅:

http://code.djangoproject.com/ticket/9039

这里的问题是,表单CharField的规范化“空白”值是一个空字符串,而不是无。因此,如果将该字段保留为空白,则会得到一个空字符串,而不是NULL,存储在数据库中。在Django和数据库规则下,空字符串等于用于唯一性检查的空字符串。

你可以通过使用clean_bar方法为Foo提供自己的自定义模型表单,从而将空字符串转换为None,从而强制管理界面为空字符串存储NULL:

class FooForm(forms.ModelForm):

class Meta:

model = Foo

def clean_bar(self):

return self.cleaned_data['bar'] or None

class FooAdmin(admin.ModelAdmin):

form = FooForm

以上是 在Django中允许为空的唯一字段 的全部内容, 来源链接: utcz.com/qa/434160.html

回到顶部