class A(models.Model):
pass
class B(models.Model):
parents = models.ManyToManyField(A, related_name='children')
>>> A._meta.get_all_field_names()
['children', u'id']
>>> B._meta.get_all_field_names()
[u'id', 'parents']
I can get the sets of children and parents of model instances with a.children.all()
and b.parents.all()
class FK(models.Model):
parent = models.ForeignKey('self', related_name='child')
>>> FK._meta.get_all_field_names()
['child', u'id', 'parent']
Any instance of FK
will now be able to get both its parent and its child with fk.parent
and fk.child
class M2M(models.Model):
parents = models.ManyToManyField('self', related_name='children')
>>> M2M._meta.get_all_field_names()
[u'id', 'parents']
One would expect that, like I could access a.children
and fk.child
, I would also be able to access m2m.children
. This seems to not be the case.
How do I access m2m.children
?
I'm using Django 1.6.5.
As Daniel Roseman's answer said, setting symmetrical=False
solves the problem. In a Django ticket it is explained as:
In the case of parent/child, the relationship isn't symmetrical - if A is a child of B, it doesn't follow that A is a parent of B.
With symmetrical=False
, the reverse relation specified in the related_name
is created just like in the foreign key case:
class M2M(models.Model):
parents = models.ManyToManyField('self', related_name='children', symmetrical=False)
>>> M2M._meta.get_all_field_names()
[u'id', 'parents', children]
>>> parent.children.add(child)
>>> parent.children.all() # returns QuerySet containing the child
>>> child.parents.all() # returns QuerySet containing the parent
You need to set symmetrical=False
. As the documentation for ManyToManyField says:
When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a person_set attribute to the Person class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.
If you do not want symmetry in many-to-many relationships with self, set symmetrical to False. This will force Django to add the descriptor for the reverse relationship, allowing ManyToManyField relationships to be non-symmetrical.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With