Django 无向唯一组合

Django undirected unique-together

我想对集合中所有成员之间的成对关系建模。

class Match(models.Model):

    foo_a = models.ForeignKey(Foo, related_name='foo_a')
    foo_b = models.ForeignKey(Foo, related_name='foo_b')

    relation_value = models.IntegerField(default=0)

    class Meta:
        unique_together = ('ingredient_a', 'ingredient_b')

当我添加一对A-B时,它成功地阻止了我再次添加A-B,但没有阻止我添加B-A。

我试过跟随,但无济于事。

unique_together = (('ingredient_a', 'ingredient_b'), ('ingredient_b', 'ingredient_a'))

编辑: 我需要 relationship_value 对于每一对项目都是唯一的

如果你像你定义的那样定义一个模型,它不仅仅是一个外键,它被称为多对多关系。

在 django 文档中,明确定义了 ManyToMany 关系不能包含唯一在一起约束。

来自文档,

A ManyToManyField cannot be included in unique_together. (It’s not clear what that would even mean!) If you need to validate uniqueness related to a ManyToManyField, try using a signal or an explicit through model.

编辑

经过大量搜索和反复试验,我认为我终于找到了适合您的情况的解决方案。是的,正如您所说,目前的架构并不像我们所有人想象的那么微不足道。在这种情况下,Many to many relation 不是我们需要转发的讨论。解决方案是,(或者我认为的解决方案是)model clean method:

class Match(models.Model):
    foo_a = models.ForeignKey(Foo, related_name='foo_a')
    foo_b = models.ForeignKey(Foo, related_name='foo_b')

    def clean(self):
        a_to_b = Foo.objects.filter(foo_a = self.foo_a, foo_b = self.foo_b)
        b_to_a = Foo.objects.filter(foo_a = self.foo_b, foo_b = self.foo_a) 

        if a_to_b.exists() or b_to_a.exists():
            raise ValidationError({'Exception':'Error_Message')})

有关模型清理方法的更多详细信息,请参阅 docs here...

我重写了对象的保存方法,每次保存2对。如果用户要添加一对A-B,则自动添加一条参数相同的记录B-A。

注意:该方案影响查询速度。对于我的项目来说,这不是问题,但需要考虑。

def save(self, *args, **kwargs):
    if not Match.objects.filter(foo_a=self.foo_a, foo_b=self.foo_b).exists():
        super(Match, self).save(*args, **kwargs)
    if not Match.objects.filter(foo_a=self.foo_b, foo_b=self.foo_a).exists():
        Match.objects.create(foo_a=self.foo_b, foo_b=self.foo_a, bar=self.bar)

编辑:当然也需要重写更新和删除方法。