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

时间:2014-07-02 15:29:31

标签: 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']

我可以使用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']

FK的任何实例现在都可以通过fk.parentfk.child

获取其父级及其子级

多对多(递归)

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

>>> M2M._meta.get_all_field_names()
[u'id', 'parents']

我可以预期,就像我可以访问a.childrenfk.child一样,我也可以访问m2m.children。情况似乎并非如此。

如何访问m2m.children

我正在使用Django 1.6.5。


供将来参考

正如Daniel Roseman's answer所说,设置symmetrical=False可以解决问题。在Django ticket中,它被解释为:

  

在父母/子女的情况下,这种关系不是对称的 - 如果A是B的孩子,那么A并不是B的父母。

使用symmetrical=Falserelated_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

1 个答案:

答案 0 :(得分:4)

您需要设置symmetrical=False。正如the documentation for ManyToManyField所说:

  

当Django处理这个模型时,它会识别出它自身有一个ManyToManyField,因此它不会向Person类添加person_set属性。相反,ManyToManyField被认为是对称的 - 也就是说,如果我是你的朋友,那么你就是我的朋友。

     

如果您不想在与self的多对多关系中进行对称,请将symmetrical设置为False。这将强制Django为反向关系添加描述符,允许ManyToManyField关系是非对称的。