简体   繁体   English

Django无向唯一在一起

[英]Django undirected unique-together

I want to model pair-wise relations between all members of a set. 我想对集合中所有成员之间的成对关系建模。

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

When I add a pair AB, it successfully prevents me from adding AB again, but does not prevent me from adding BA. 当我添加一对AB时,它成功阻止我再次添加AB,但是并不能阻止我添加BA。

I tried following, but to no avail. 我尝试跟随,但无济于事。

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

Edit: I need the relationship_value to be unique for every pair of items 编辑:我需要为每对项目都唯一的relationship_value

If you define a model like what you defined, its not just a ForeignKey, its called a ManyToMany Relation. 如果您按照定义的方式定义模型,则不仅是外键,还称为ManyToMany Relation。

In the django docs, it is explicitly defined that unique together constraint cannot be included for a ManyToMany Relation. 在Django文档中,明确定义了对于ManyToMany Relation不能包括唯一的共同约束。

From the docs, 从文档中

A ManyToManyField cannot be included in unique_together. ManyToManyField不能包含在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. (尚不清楚这意味着什么!)如果您需要验证与ManyToManyField相关的唯一性,请尝试使用信号或显式直通模型。

EDIT 编辑

After lot of search and some trial and errors and finally I think I have found a solution for your scenario. 经过大量搜索和反复试验后,我终于找到了针对您的方案的解决方案。 Yes, as you said, the present schema is not as trivial as we all think. 是的,正如您所说,目前的架构并不像我们所有人认为的那么琐碎。 In this context, Many to many relation is not the discussion we need to forward. 在这种情况下,多对多关系不是我们需要转发的讨论。 The solution is, (or what I think the solution is) 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')})

For more details about model clean method, refer the docs here... 有关模型清理方法的更多详细信息,请参阅此处文档...

I've overridden the save method of the object to save 2 pairs every time. 我重写了对象的save方法,每次都保存2对。 If the user wants to add a pair AB, a record BA with the same parameters is automatically added. 如果用户要添加一对AB,则会自动添加具有相同参数的记录BA。

Note: This solution affects the querying speed. 注意: 此解决方案会影响查询速度。 For my project, it is not an issue, but it needs to be considered. 对于我的项目,这不是问题,但是需要考虑。

 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) 

EDIT: Update and remove methods need to be overridden too of course. 编辑:当然,更新和删除方法也需要被覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM