Django OneToOneField with Multiple Same Names

Sorry for the non-descriptive name, but I really had no idea how to say it.

Let's say I have two models:

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 that calling dad.family would give me the dad family. However, I get an error message stating that this is a collision with mum . The solution here is to use relative_name s. But calling the family from the mum side of something else than from the dad seems strange to me. Why can't I just call dad.family ? Can someone explain to me what exactly is going on here?

Thanks!

+4
source share
2 answers

The problem is that given your model, Person may be mum for one family and dad for another family.

In this case, such a request will 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 this reason, you need to define a feedback name for each of them (for example, family_as_mum and family_as_dad)

+4
source

I know that the answer above answers the question “why does it collide”, and I know that this is an old question. However, I stumbled upon this while trying to find a way to limit the number of records in one column based on the records in another. I did not find a sufficient answer, but I managed to figure it out myself. Below is the answer to a question that is not directly asked, but may be useful 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=SET_NULL, related_name='family_as_mum') dad = models.OneToOneField(Person, on_delete=SET_NULL, related_name='family_as_dad') 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 

* pay attention, I found @staticmethod here, I thought it would be useful to have a function for finding a family associated with a parent, since we may not know the front if the person is mom or dad

0
source

Source: https://habr.com/ru/post/1437628/


All Articles