如何根据两个字段其中一个是可选字段在具有UniqueConstraint的Django模型中的空值或NULL之间进行选择?

问题描述

我有一个基于两个字段值的,具有Uniqueconstraint的Django模型,其中一个是强制性的,后者是可选的。

对于“可选”字段(以及为什么)在以下位置存储“无值”的最佳实践是什么?

  1. 无值=空
  2. 无值= NULL

models.py

class Foos(models.Model):
    name =  models.CharField(max_length=50,blank=False,null=False)
    # Optional field
    alias = models.CharField(max_length=100,blank=True,null=True)

    class Meta:
        managed = True
        db_table = 'foos'

    def __str__(self):
        constraints = [models.UniqueConstraint(fields=['name','alias'],name='unique_foo')]
        object_name = self.name
        return object_name 

请注意,我需要从外部源文件中插入一堆值,“ alias”的值可能等于“ None”。

附录:实际上,可以通过两种方式从表单和Excel文件中插入数据。基于表单的插入如下所示,因此我最终得到了具有空值和NULL的字段别名,这从约束的角度来看是令人讨厌的,如果别名为NULL或为空,则必须执行该字段别名,这就是为什么我要求“最佳实践”在这里

forms.py

class FooCreateForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        
        self.fields['name'] = forms.CharField(label='Name',widget=forms.TextInput(attrs={ 'class': 'form-control' }))
        self.fields['alias'] = forms.CharField(label='Alias',required=False,widget=forms.TextInput(attrs={ 'class': 'form-control' }))

    class Meta(object):
        model = Foos
        fields = ('name','alias')
        
    def clean_name(self):
        name = self.cleaned_data['name']
        return name
        
    def clean_alias(self):
        alias = self.cleaned_data['alias']
        return alias  

my_importer.py

# Only relevant code mentionned

foos_imported = []

for foo in foos:
    foo_name = foo["Name"]
    
    if not Foos.objects.filter(name=foo_name,alias=foo["Alias"]):
        foo_obj = Foos(
                          name=foo["Name"],alias=foo["Alias"],)
        
        try:
          foo_obj.save()
          foos_imported.append(foo)

        except Exception as e:
            logger.error("Can't create foo {} : {}".format(foo["Name"],e.args))    
                
    else:
        logger.warning("Foo \"{}\" already exists within database,it won't be imported".format(foo_name))

解决方法

您可以使用name="a"alias=None添加多个Foos。但您只能有一对name="a"alias=""