Django对称关系

时间:2015-02-03 20:17:37

标签: django relation symmetric

我试图用一个Person模型将married_to字段作为外键的网站解决一个简单的问题。

当用户(PersonA)改变他/她与以下人士结婚的人时,要保持这一点:

  • PersonA结婚的前任人员应将其已婚领域设为无
  • PersonA与之结婚的新人应该更新并将其已婚领域设置为PersonA(这反过来可以触发新人可能已经结婚的人应该将其已婚领域设置为无)

所以我尝试的是在行

中覆盖save方法
    if self.pk is not None and self.married is not None:
        orig = Person.objects.get(pk=self.pk)
        orig.married.married = None
        orig.married.save()

    if self.married is not None:
        self.married.married = self
        self.married.save()

    super(Person, self).save()

我遇到了最大的递归问题等,并开始寻找答案,但没有找到任何结论。

为像我这样的新手做这件事的惯用方法是什么......

由于

3 个答案:

答案 0 :(得分:1)

选项1 编写代码,避免保存方法调用:

if self.pk is not None and self.married is not None:
    Person.objects.filter(pk=orig.married.married.pk).update( married = None )

if self.married is not None:
    Person.objects.filter(pk=orig.married.pk).update( married = self )

super(Person, self).save()

选项2 此外,您可以使用条件特定情况停止递归:

if self.married is not None and self.married != self:
    self.married.married = self
    self.married.save()

正确的方式也许,您的方案中的正确关系是OneToOneField(您在问题中谈论ForeignKey)如果一个人只能与另一个人结婚之一。

答案 1 :(得分:0)

我会将其作为一个单独的方法实现,而不是作为save()的一部分。假设"结婚"是相关人员的FK:

class Person(models.Model):
    [...]
    def set_married(self, married_to):
        if self.married_id != married_to.id:   # <-- prevent recursion/looping
            self.married = married_to
            self.save()
            self.married.set_married(self)

答案 2 :(得分:0)

这样的事情会起作用。

class Person(models.Model):
    ...
    partner = models.OneToOneField('self', blank=true, null=true)

    def save(self, *args, **kwargs):
       # to avoid infinite looping on save.
       if not self.partner.partner:
            self.partner.partner = self
            self.partner.save()

这将仅保存相等的伙伴字段(创建对称关系)。