我有带场地wine 吧的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个foo对象,其中bar为null时,它会给我一个错误:"具有此bar的foo已经存在."

然而,当我插入数据库(PostgreSQL)时:

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

这很管用,很好,它允许我插入多条记录,条为空,所以数据库允许我做我想做的事情,这只是Django模型出了问题.有什么 idea 吗?

编辑

就DB而言,解决方案的可移植性不是问题,我们对Postgres很满意. 我try 了对一个可调用函数进行唯一的设置,即我的函数为特定值bar返回True/False,它没有给出任何错误,但是看起来一点效果都没有.

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

推荐答案

自票证#9039被修复以来,Django在唯一性判断中没有将NULL视为等于NULL,请参见:

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

这里的问题是Form Charfield的规范化"空白"值是空字符串,而不是无.因此,如果将该字段保留为空,则会得到一个存储在数据库中的空字符串,而不是NULL.在Django和数据库规则下,空字符串等同于用于唯一性判断的空字符串.

您可以强制管理界面为空字符串存储NULL,方法是为foo提供自己的自定义模型表单,并使用CLEAN_BAR方法将空字符串转换为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、htmx删除记录并更新

与django相关的预取n +1问题.我该怎么解决呢?

Django动态页面.为什么我的代码不工作?

DjangoAdmin与外部数据库的模型无法保存或过滤

Django 注释(),计数()

Django `UniqueConstraint` 异常处理方式与 'unique=True' 相同

如何在 Django 中将下一个 8 月 1 日添加为 DateTimeField 默认值

Django 从 url 保存图像并与 ImageField 连接

如何从 django 自定义中间件类返回 rest_framework.response 对象?

NoReverseMatch 错误

如何在django中生成临时文件然后销毁

在 django 中的查询集上运行 explain的简单方法

使用 sqlite 运行 django 测试

如何在 Django 中触发 500 错误?

将 Django Rest Framework 与序列化程序一起使用时出现 AttributeError

Django - 一起为 2 个或更多字段创建唯一的数据库约束

ModelForm 上的 Django 和字段集

有没有一种简单的方法可以从 CharField 填充 SlugField?

何时使用 Django get_absolute_url() 方法?

我将如何package打包和销售 Django 应用程序?