Just to add, I don't think django supports symmetrical M2M relations with
additional data / explicit through model without the shim I suggested.
For example, this works:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=255)
friends = models.ManyToManyField("self", symmetrical=True)
def __str__(self):
return self.name
>>> from people.models import Person
>>> bill = Person.objects.create(name='bill')
>>> ted = Person.objects.create(name='ted')
>>> bill.friends.add(ted)
>>> bill.friends.all()
<QuerySet [<Person: ted>]>
>>> ted.friends.all()
<QuerySet [<Person: bill>]>
On 17 Oct 2020, at 10:28, coolguy
<[email protected]<mailto:[email protected]>> wrote:
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.models
from 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<http://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]<mailto:[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<https://groups.google.com/d/msgid/django-users/f1b39d06-6100-4b6c-94a5-1ec60fa45f80n%40googlegroups.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/A978B24A-1041-4850-AABA-224F2EFD2E9E%40uniquode.io.