from django.db import models
class Person(models.Model):
name = models.CharField(max_length=255)
friends = models.ManyToManyField("self", through='Friendship', symmetrical=True)
def __str__(self):
return self.name
class Friendship(models.Model):
person_a = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='a')
person_b = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='b')
start = models.DateField(auto_now_add=True)
def __str__(self):
return f'{self.person_a.name} => {self.person_b.name}: {self.start}'
>>> from people.models import Person, Friendship
>>> bill = Person.objects.create(name='bill')
>>> rufus = Person.objects.create(name='rufus')
>>> bill.friends.add(ted)
>>> bill.friends.add(rufus)
>>> rufus.friends.add(bill)
>>> rufus.friends.add(ted)
>>> bill.friends.all()
<QuerySet [<Person: ted>, <Person: rufus>]>
>>> ted.friends.all()
<QuerySet [<Person: bill>, <Person: rufus>]>
>>> rufus.friends.all()
<QuerySet [<Person: bill>, <Person: ted>]>
>>> Friendship.objects.all()
<QuerySet [
<Friendship: bill => ted: 2020-10-17>,
<Friendship: ted => bill: 2020-10-17>,
<Friendship: bill => rufus: 2020-10-17>,
<Friendship: rufus => bill: 2020-10-17>,
<Friendship: rufus => ted: 2020-10-17>,
<Friendship: ted => rufus: 2020-10-17>
]>
In your case, naming the related_name the same as the field name may be an issue. Since related_name becomes a pseudo field on the model in which it is defined, so there is a potential clash in the namespace?
On 17 Oct 2020, at 11:20, gjgilles via Django users <django-users@googlegroups.com> wrote:
Thanks for all for the replies!
@David, the helper function works as expected.
>>> from people.models import Person, Friendship
>>> bill = Person(name='bill')
>>> bill.save()
>>> ted = Person(name='ted')
>>> ted.save()
>>> bill.add_friendship(ted, True)
(<Friendship: bill and ted>, True)
>>> bill.friends.all()
<QuersySet [<Person: ted>]>>>> ted.friends.all()
<QuerySet [<Person: bill>]>
Also, @coolguy for my code, the correct call is >>> ted.personB.all() without the helper function. ted.personA.all() returns an empty queryset without the helper function.
"Recursive relationships using an intermediary model and defined as symmetrical (that is, with symmetrical=True, which is default) can't determine the accessory names, as they would be the same. You need to set a related_name to at least one of them. If you'd prefer Django not to create a backwards relation, set related_name to '+'."
This implies Django makes the reverse relation by default. Am I misunderstanding something?
No comments:
Post a Comment