Reputation: 814
I was trying to solve a simple problem with a site where a Person model has a married_to field as Foreign Key.
To maintain this when a user (PersonA) changes who he/she is married to the following should happen:
So what I tried was to override the save method something along the lines
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()
I ran into maximum recursive problem etc. and started to search for answers but didnt find anythin conclusive.
What is the idiomatic way to do this for noobs like me...
Thanks
Upvotes: 2
Views: 214
Reputation: 51705
option 1 Write your code avoid save method call:
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()
option 2 Also, you can stop recursion with a conditional particular case:
if self.married is not None and self.married != self:
self.married.married = self
self.married.save()
right way Perhaps, the right relation in your scenario is OneToOneField ( you are talking about ForeignKey in your question) if a Person can be only be married with another one.
Upvotes: 1
Reputation: 13
Something like this will work.
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()
This will on save simply equal partner fields (create a symmetrical relation).
Upvotes: 0
Reputation: 1736
I would implement this as a separate method, not as a part of save(). Assuming that "married" is an FK to the related Person:
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)
Upvotes: 0