递归的相关名称多对多关系不起作用

ker*_*ryz 10 django django-models

多对多(非递归)

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']
Run Code Online (Sandbox Code Playgroud)

我能得到孩子们的集合,并与模型实例的父母a.children.all()b.parents.all()

外键(递归)

class FK(models.Model):
    parent = models.ForeignKey('self', related_name='child')


>>> FK._meta.get_all_field_names()
['child', u'id', 'parent']
Run Code Online (Sandbox Code Playgroud)

的任何实例FK现在将能够同时获得其母公司和其子带fk.parentfk.child

多对多(递归)

class M2M(models.Model):
    parents = models.ManyToManyField('self', related_name='children')

>>> M2M._meta.get_all_field_names()
[u'id', 'parents']
Run Code Online (Sandbox Code Playgroud)

人们期望的是,像我可以访问a.childrenfk.child,我也能够访问m2m.children.情况似乎并非如此.

我如何访问m2m.children

我正在使用Django 1.6.5.


备查

正如Daniel Roseman的回答所说,设置symmetrical=False解决了问题.在Django票中,它被解释为:

在父/子的情况下,关系不是对称的 - 如果A是B的孩子,则不遵循A是B的父亲.

使用时symmetrical=False,创建的反向关系related_name就像在外键情况下一样创建:

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
Run Code Online (Sandbox Code Playgroud)

Dan*_*man 7

您需要设置symmetrical=False。正如ManyToManyField的文档所述

Django处理此模型时,会确定其自身具有ManyToManyField,因此,不会向Person类添加person_set属性。相反,假定ManyToManyField是对称的-也就是说,如果我是您的朋友,那么您就是我的朋友。

如果您不希望与自己的多对多关系具有对称性,请将“对称性”设置为“ False”。这将迫使Django为反向关系添加描述符,从而允许ManyToManyField关系是非对称的。