简体   繁体   English

Django-对称外键或ManyToMany中的级联删除?

[英]Django - Symmetrical ForeignKeys or cascade deletion in ManyToMany?

I had a model that looked something like this: 我有一个看起来像这样的模型:

class Bar(models.Model):
    foo1 = models.ForeignKey(Foo, related_name='bar_foo1')
    foo2 = models.ForeignKey(Foo, related_name='bar_foo2')

    class Meta:
        unique_together = ('foo1', 'foo2')

The problem was that foo1 and foo2 need to have the same behavior when they are inverted. 问题在于,当foo1foo2反转时,它们必须具有相同的行为。 In other words, it's something like: "If you liked foo1 you may want to check foo2 out", which should apply the other way around ("If you liked foo2 you may want to check foo1 out"). 换句话说,它类似于:“如果您喜欢foo1,则可能要签出foo2”,这应该采用相反的方式(“如果您喜欢foo2,则可能要签出foo1”)。

So I used a ManyToMany field instead of ForeignKey to make them symmetrical: 所以我使用ManyToMany字段而不是ForeignKey使它们对称:

class Bar(models.Model):
    foos = models.ManyToManyField(Foo)

Using a signal to make sure there are never more than 2 foos : 使用信号确保不超过2个foos

def foos_changed(sender, **kwargs):
    if kwargs['instance'].foos.count() > 2:
        raise ValidationError("You can't assign more than two foos.")    

m2m_changed.connect(foos_changed, sender=Bar.foos)

However, this creates another problem, which is in case a Foo in foos is deleted, the Bar just stays there, but it should be deleted as well (which is solved by cascade deletion in ForeignKeys). 但是,这会带来另一个问题,如果foosFoo被删除, Barfoos ,但是也应该将其删除(这通过ForeignKeys中的级联删除来解决)。

How can I solve this? 我该如何解决? Can I make ForeignKeys symmetrical? 我可以使外键对称吗? Or implement cascade deletion in ManyToMany? 还是在ManyToMany中实现级联删除? Or is there another way to solve this? 还是有解决此问题的另一种方法?

I have done this before, the easiest way is to create a pseudo constructor for the model instance that makes sure that item 1 and item 2 are always in order (I used alphabetical but you might as well use id) which makes your uniqueness work ootb. 我之前已经做过,最简单的方法是为模型实例创建一个伪构造函数,以确保第1项和第2项始终按顺序排列(我使用字母顺序,但您也可以使用id),这使您的唯一性起作用。

In the lookups you just look for your item in foo1 or foo2 since you dont mind in which side of the relation it is, which provides the bidirectionality. 在查找中,您只需要在foo1或foo2中查找项目,因为您不介意关系的哪一边,它提供了双向性。

With a few helpers here and there you have a smart object that provides recommendations. 在这里和那里有一些帮助者,您将拥有一个提供建议的智能对象。

Another more extensible approach is to create a table containing only names for recommendation groups and then m2m objects to recommendation groups so you have a group of foos to recommend, the lookup is easier: foo ->group -> many foos 另一个更可扩展的方法是创建一个仅包含推荐组名称的表,然后创建指向推荐组的m2m对象,因此您可以推荐一组foos,查找起来更容易:foo-> group-> many foos

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

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