在Django中实现字段的唯一组合

时间:2014-04-17 15:36:46

标签: django django-models foreign-key-relationship

有一个模型可以链接多个项目,例如:

from django.db import models

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

    def __unicode__(self):
        return self.name

class MyModelItem(models.Model):
    TYPE_CHOICES = (
        ('A', 'A NAME'),
        ('B', 'B NAME'),
        ('C', 'C NAME')
    )
    name = models.CharField(max_length=100)
    model = models.ForeignKey(MyModel, related_name='items')
    item_type = models.CharField(max_length=1, choices=TYPE_CHOICES)

    def __unicode__(self):
        return self.name

要求是:对于MyModel的每条记录,不允许多条记录MyModelItem具有相同的item_type,这意味着如果我有:{/ p >

from myproj.myapp.models import MyModel, MyModelItem

m1 = MyModel.objects.create(name='M1')

MyModelItem.objects.create(name='Item1', model=m1, item_type='A')

然后我无法向m1添加具有相同类型“A”的其他记录。

对我来说,一个解决方案就是在MyModelItem中执行此操作:

    ...
    def save(self, *args, **kwargs):
        if self.model.items.filter(item_type=self.item_type):
            raise IntegrityError("%s already have a item with type %s" % (self.model, self.item_type))
        super(MyModelItem, self).save(*args, **kwargs)

但这不会保护数据库级别的限制。可以直接用SQL添加这些不允许的记录,它可能会破坏我的应用程序。有没有办法在Django中实现这个要求?像unique_together

这样的东西

1 个答案:

答案 0 :(得分:4)

你明白了,unique_together是这样做的方法。它很简单:

class MyModelItem(models.Model): 
    ...
    name = models.CharField(max_length=100)
    model = models.ForeignKey(MyModel, related_name='items')
    item_type = models.CharField(max_length=1, choices=TYPE_CHOICES)

    class Meta:
        unique_together = ('model', 'item_type')