With your example, you can also find the records through>>> ted.person_set.all().
On Friday, October 16, 2020 at 7:05:51 PM UTC-4 David Nugent wrote: > This is expected with your code. You've created an asymmetric > relationship from bill to ted, but not the reverse. This would be > appropriate in a "follow" relationship. For symmetric relationships you > need to create records in both directions. There are a few ways to do this > but a helper function on the Person model is the most direct approach, > something along the lines: > > def add_friendship(self, person, symmetric=True): > friendship = Friendship.objects.get_or_create(personA=self, > personB=person) > if symmetric: > # avoid recursion > person.add_friendship(self, False) > return friendship > > > Regards, David > > On 17 Oct 2020, at 05:38, gjgilles via Django users < > [email protected]> wrote: > > There are no responses to the same question on stackoverflow, so hopefully > someone here can provide a solution. > <https://stackoverflow.com/questions/64346385/how-to-make-a-recursive-manytomany-relationship-symmetrical-with-django> > > > I've read the docs. > <https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ManyToManyField.symmetrical> > I've read this question too, > <https://stackoverflow.com/questions/4129439/how-to-make-recursive-manytomanyfield-relationships-that-have-extra-fields-symme> > but the following code is not working as the Django docs describe. > If *bill* and *ted *are friends,* bill.friends.all() *should include > *ted, *and *ted.friends.all() *should include *bill*. This is not what > Django does. *ted*'s query is empty, while *bill*'s query includes *ted*. > > # people.modelsfrom django.db import models > > class Person(models.Model): > name = models.CharField(max_length=255) > friends = models.ManyToManyField("self", > through='Friendship', > through_fields=('personA', 'personB'), > symmetrical=True, > ) > > def __str__(self): > return self.name > > class Friendship(models.Model): > personA = models.ForeignKey(Person, on_delete=models.CASCADE, > related_name='personA') > personB = models.ForeignKey(Person, on_delete=models.CASCADE, > related_name='personB') > start = models.DateField(null=True, blank=True) > end = models.DateField(null=True, blank=True) > > def __str__(self): > return ' and '.join([str(self.personA), str(self.personB)]) > > > > > >>> import django > >>> django.__version__ > '3.1.2' > >>> from people.models import Person, Friendship>>> bill = > >>> Person(name='bill')>>> bill.save()>>> ted = Person(name='ted')>>> > >>> ted.save()>>> bill_and_ted = Friendship(personA=bill, personB=ted)>>> > >>> bill_and_ted.save()>>> bill.friends.all() > <QuerySet [<Person: ted>]>>>> ted.friends.all() > <QuerySet []>>>> ted.refresh_from_db()>>> ted.friends.all() > <QuerySet []>>>> ted = Person.objects.get(name='ted')>>> ted.friends.all() > <QuerySet []> > > > Can someone please show me how to make this behave as expected. > > > -- > You received this message because you are subscribed to the Google Groups > "Django users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-users/MJmh5Qw--3-2%40tutanota.com > <https://groups.google.com/d/msgid/django-users/MJmh5Qw--3-2%40tutanota.com?utm_medium=email&utm_source=footer> > . > > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/f1b39d06-6100-4b6c-94a5-1ec60fa45f80n%40googlegroups.com.

