django - Django 中允许空值的唯一字段

标签 django orm django-models

我有一个模型 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/

相关文章:

Python Django equals 在函数参数中。动态设置变量

django - 如何在heroku上为django应用程序安装ffmpeg?

python - key 错误 : 'locations' in Django app

python - Django 2.0.7 URL app_name 如何工作

Django - 多态模型还是一个大模型?

java - ORM 和对象映射之间的区别?

php - Doctrine 说我应该在显式字段中拆分参数,但我的 ID 为空

javascript - 是否有一个好的框架或方法来重构 JavaScript 对象?

Django - 更改 'upload file' 按钮在模板中显示的内容

django - 使用 URLField 优于 TextField 的优势?