【问题标题】:unique_together constraint on multiple columns with NULL values具有 NULL 值的多个列的 unique_together 约束
【发布时间】:2014-10-15 18:59:11
【问题描述】:

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

如何定义unique_together 约束以确保full_name 在数据库级别的唯一性?如果缺少品牌名称(即brand_id ForeignKeyNULL),当前约束允许多个具有相同名称的部件

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

使用:Django 1.6 + PostgreSQL 9.3

附:这里有一个很好的建议来使用 SQL 实现这一点。我正在寻找使用 Django ORM 的解决方案。 https://stackoverflow.com/a/8289253/781695

【问题讨论】:

标签: django postgresql django-models


【解决方案1】:

恐怕没有办法告诉 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')

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

【讨论】:

  • 请注意,这是由 ModelForm 调用的,但不是在调用 save
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多