在Django中允许null的唯一字段

在Django中允许null的唯一字段

本文介绍了在Django中允许null的唯一字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有模型Foo,它有现场栏。 bar字段应该是unque,但是在其中允许null,这意味着如果bar字段为null,我想允许多个记录,但是如果它不为null,则值必须为unque。



这是我的模型:

  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字符变化(40)NOT NULL,
bar字符变化(40),
CONSTRAINT appl_foo_pkey主键(id),
CONSTRAINT appl_foo_bar_key UNIQUE(bar)

admin界面创建超过1个foo对象,其中bar为null它给我一个错误:这个Bar的Foo已经存在。



但是当我插入到数据库Postgre SQL)

  insert into appl_foo(name,bar)values('test1',null)
insert进入appl_foo(name,bar)值('test2',null)

好的,它允许我插入超过1条记录,bar为null,所以数据库允许我做我想要的,这只是Django模型的错误。任何想法?



编辑



解决方案的可移植性到DB不是一个问题,我们对Postgres感到满意。
我已经尝试设置为可调用的唯一,这是我的函数返回True / False的具体值 bar ,它没有给出任何错误,但是如果它没有效果,



到目前为止,我已经从属性中移除了唯一的说明符,并处理了应用程序的独特性,但仍然寻找一个更优雅的解决方案。任何建议?

解决方案

为了独特性检查,Django并没有将NULL等同于NULL,因为票证#9039已被修复,请参阅:





这里的问题是表单CharField的归一化空白值是空字符串,而不是无。所以如果你把这个字段留空,你会得到一个空的字符串,而不是NULL,存储在数据库中。空字符串等于使用Django和数据库规则进行唯一性检查的空字符串。



您可以强制管理界面通过提供自己的空字符串来存储空字符串Foo的自定义模型窗体使用clean_bar方法将空字符串转换为None:

  class FooForm(forms.ModelForm):
class Meta:
model = Foo
def clean_bar(self):
return self.cleaned_data ['bar']或None

class FooAdmin(admin .ModelAdmin):
form = FooForm


I have model Foo which has field bar. The bar field should be unque, but allow nulls in it, meaning I want to allow more than one record if bar field is null, but if it is not null the values must be unque.

Here is my model:

class Foo(models.Model):
    name = models.CharField(max_length=40)
    bar = models.CharField(max_length=40, unique=True, blank=True, null=True, default=None)

And here is the corresponding SQL for the table:

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)
)

When using admin interface to create more than 1 foo objects where bar is null it gives me an error: "Foo with this Bar already exists."

However when I insert into database (PostgreSQL):

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

This works, just fine, it allows me to insert more than 1 record with bar being null, so the database allows me to do what I want, it's just something wrong with the Django model. Any ideas?

EDIT

The portability of the solution as far as DB is not an issue, we are happy with Postgres.I've tried setting unique to a callable, which was my function returning True/False for specific values of bar, it didn't give any errors, however seamed like it had no effect at all.

So far, I've removed the unique specifier from the bar property and handling the bar uniqueness in the application, however still looking for a more elegant solution. Any recommendations?

解决方案

Django has not considered NULL to be equal to NULL for the purpose of uniqueness checks since ticket #9039 was fixed, see:

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

The issue here is that the normalized "blank" value for a form CharField is an empty string, not None. So if you leave the field blank, you get an empty string, not NULL, stored in the DB. Empty strings are equal to empty strings for uniqueness checks, under both Django and database rules.

You can force the admin interface to store NULL for an empty string by providing your own customized model form for Foo with a clean_bar method that turns the empty string into 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中允许null的唯一字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 15:36