我有一个模型 Foo,它有字段栏。条形字段应该是唯一的,但允许其中有空值,这意味着如果条形字段为 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)
)
当使用管理界面创建超过 1 个 bar 为 null 的 foo 对象时,它给我一个错误:“Foo with this Bar already exists.”
但是当我插入数据库(PostgreSQL)时:
insert into appl_foo ("name", bar) values ('test1', null)
insert into appl_foo ("name", bar) values ('test2', null)
这很好用,它允许我插入 1 条以上的记录且 bar 为空,因此数据库允许我做我想做的事,这只是 Django 模型的问题。有什么想法吗?
编辑
就数据库而言,解决方案的可移植性不是问题,我们对 Postgres 很满意。 我试过为可调用对象设置唯一性,这是我的函数为 bar 的特定值返回 True/False,它没有给出任何错误,但是缝合起来就像它根本没有效果。
到目前为止,我已经从 bar 属性中删除了唯一说明符并处理了应用程序中的 bar 唯一性,但仍在寻找更优雅的解决方案。有什么建议吗?
最佳答案
Django 没有将 NULL
视为等于 NULL
以进行唯一性检查,因为票证 #9039 已修复,请参阅:
http://code.djangoproject.com/ticket/9039
这里的问题是表单 CharField
的规范化“空白”值是一个空字符串,而不是 None
。因此,如果您将该字段留空,您将得到一个空字符串,而不是 NULL
,存储在数据库中。在 Django 和数据库规则下,空字符串等于用于唯一性检查的空字符串。
您可以通过使用 clean_bar
方法为 Foo
提供您自己的自定义模型表单,强制管理界面为空字符串存储 NULL
将空字符串变成 None
:
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 - Django 中允许空值的唯一字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/454436/