对具有NULL值的多个列的unique_together约束

use*_*ser 3 django postgresql django-models

我有一个汽车零件数据库,包括品牌和非品牌商品.如果品牌名称不可用,full_name那就简单了Part.name,否则就是Brand.name + Part.name.

如何定义unique_together约束以确保full_name数据库级别的唯一性?目前的约束允许具有相同名称的多个部分,如果品牌名称缺失(即brand_id ForeignKey是NULL)

class Brand(models.Model):
    name = models.CharField(max_length=100)

class Part(models.Model);
    name = models.CharField(max_length=100)
    brand = models.ForeignKey(Brand, null=True, blank=True)

    def get_full_name(self):
        if self.brand_id:
            full_name = '%s %s'.format(self.brand.name, self.name)
        else:
            full_name = self.name
        return full_name

    class Meta:
        unique_together = (('name', 'brand'),) 
Run Code Online (Sandbox Code Playgroud)

使用:Django 1.6 + PostgreSQL 9.3

PS这里有一个很好的建议,用SQL实现这一点.我正在寻找使用Django ORM的解决方案./sf/answers/580247741/

Gre*_*reg 5

没有办法告诉django添加那个索引我害怕,unique_together只处理简单的索引.但是,您可以使用clean在保存模型实例之前调用的方法在模型层验证(ModelForm实例为您调用):

from django.core.validators import ValidationError

class Part(models.Model):

    def clean(self):
        duplicates = Part.objects.exclude(pk=self.pk).filter(name=self.name)
        if self.brand:
            duplicates = duplicates.filter(brand=self.brand)
        if duplicates.count():
            raise ValidationError(u'Duplicate part/brand')
Run Code Online (Sandbox Code Playgroud)

理想情况下,您应该使用RunSQL迁移中的操作手动将索引添加到Postgres数据库.

  • 请注意,这是由ModelForm调用的,但是当调用`save`时**不是** (2认同)