2

我试图解决一个网站的简单问题,其中 Person 模型有一个 mapped_to 字段作为外键。

为了在用户 (PersonA) 更改他/她的结婚对象时保持这一点,应该发生以下情况:

  • PersonA 与之结婚的前一个 Person 应该将它的 mapped-field 设置为 None
  • PersonA 与之结婚的新人应该更新并将其结婚字段设置为 PersonA(这反过来可以触发新人的可能先前已婚的人应该将其结婚字段设置为无)

所以我尝试的是按照以下方式覆盖保存方法

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

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

对于像我这样的菜鸟来说,这样做的惯用方法是什么......

谢谢

4

3 回答 3

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

于 2015-02-03T20:33:58.413 回答
0

我会把它作为一个单独的方法来实现,而不是作为 save() 的一部分。假设“married”是相关 Person 的 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)
于 2015-02-03T20:40:17.193 回答
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()

这将简单地保存相等的合作伙伴字段(创建对称关系)。

于 2015-02-03T20:49:05.223 回答