Reputation:
Sorry for the none-descriptive title, but I didn't really have a clue as to how to word this.
Say I have two models as such:
class Person(...):
name = ... #have an attribute
class Family(...):
mum = models.OneToOneField(Person)
dad = models.OneToOneField(Person)
When I have a family containing mum
and dad
, I would think calling dad.family
would yield me the family dad
is in. However, I get an error message saying that this clashes with the mum
attribute. The solution here is to use relative_name
s. But calling the family from mum
s side something else than from dad
s feels weird for me. WHy can't I just call dad.family
? Could someone explain to me what exactly is clashing here?
Thanks!
Upvotes: 7
Views: 5033
Reputation: 149
I know the answer above does answer the question of "why is it clashing", and I know it is an old question. However, I came across it trying to come up with a way to have the code restrict the entries in one column based on the entries in the other. I did not find a sufficient answer, but managed to puzzle it out myself. Below is an answer to a question that isn't directly asked, but may be helpful to others.
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=255)
class Family(models.Model):
mum = models.OneToOneField(Person, on_delete=models.SET_NULL, related_name='family_as_mum', null=True)
dad = models.OneToOneField(Person, on_delete=models.SET_NULL, related_name='family_as_dad', null=True)
def save(self, *args, **kwargs):
if Family.objects.filter(mum=self.dad).exists() or Family.objects.filter(dad=self.mum).exists() or self.mum == self.dad:
return #any person can only be a mum or a dad, not both
else:
super(Family, self).save(*args, **kwargs)
def update(self, *args, **kwargs):
if Family.objects.filter(mum=self.dad).exists() or Family.objects.filter(dad=self.mum).exists() or self.mum == self.dad:
return #same as save, don't want them to update a family member in an invalid way
else:
super(Family, self).update(*args, **kwargs)
@staticmethod
def get_family(person):
if Family.objects.get(mum=person).exists():
return Family.objects.get(mum=person)
elif Family.objects.get(dad=person).exists():
return Family.objects.get(dad=person)
else:
return None
*note, found the @staticmethod here, thought it might be useful to have a function to find the family associated with a parent, since we may not know up front if a person is a mum or a dad
Upvotes: 2
Reputation: 44152
The problem is that, given your model, a Person
could be a mum
to one Family, and a dad
to a different family.
In that case, a query like this would be ambiguous:
pat = Person.objects.get(name='Pat')
family1.mum = pat
family1.save()
family2.dad = pat
family2.save()
pat.family # Which family do we want?
For that reason, you need to define a reverse relation name for each one (family_as_mum and family_as_dad, for instance)
Upvotes: 7