【问题标题】:Two ManyToMany relations to the same model via the same intermediate model in Django通过 Django 中的同一中间模型与同一模型建立两个多对多关系
【发布时间】:2017-04-21 22:46:39
【问题描述】:

我的模型:

class Person(SchoolModel):
    first_name = models.CharField(max_length=75)
    last_surname = models.CharField(max_length=75)

    students = models.ManyToManyField('self', through='StudentParent',
        through_fields=('parent', 'student'), related_name='+')
    parents = models.ManyToManyField('self', through='StudentParent',
        through_fields=('student', 'parent'), related_name='+')


class StudentParent(SchoolModel):
    student = models.ForeignKey('Person')
    parent = models.ForeignKey('Person')
    relation = models.CharField(max_length=26)

    class Meta:
        unique_together = ('student', 'parent')

如上所示,Person 模型与自身有两个 m2m 关系:学生和父母。每个人在同一张 Person 表上可能有很多学生,也可能有很多父母。

但是,Django 不允许这样做:

Person: (models.E003) The model has two many-to-many relations through  
the intermediate model 'StudentParent'.

我不明白为什么 Django 拒绝这样做,尤其是因为它不使用自定义中间表保存或验证 m2m 字段。另一方面,我只需要使用这些字段来更轻松地检索相关模型。例子:

person_obj.students.all()
Person.objects.filter(parents__in=another_person_queryset)

所以我的问题是,1)在 Django1.11 中有没有办法解决这个问题(通过配置等使这样的 2 m2m 字段成为可能)? 2) 有没有办法通过其他方式使只读场景发生这种情况?

是否会使用中介模型的代理来欺骗 django 来实现 1)? 使用自定义管理器是否有助于实现 2)?最短、最整洁的路径是什么?

注意:我知道之前有人问过类似的question,但它有点不同而且有点旧。

【问题讨论】:

  • 我不明白你想在这里做什么。为什么不能只使用studentsparents 作为related_name

标签: django django-models django-1.11


【解决方案1】:

似乎通过代理模型欺骗 Django 可以达到我上面描述的目的(检索模型实例的相关数据或在过滤查询集中)。所以模型变成:

class Person(SchoolModel):
    first_name = models.CharField(max_length=75)
    last_surname = models.CharField(max_length=75)

    students = models.ManyToManyField('self', through='StudentParentProxy', # << !!!!!!
        through_fields=('parent', 'student'), related_name='+')
    parents = models.ManyToManyField('self', through='StudentParent',
        through_fields=('student', 'parent'), related_name='+')


class StudentParent(SchoolModel):
    student = models.ForeignKey('Person')
    parent = models.ForeignKey('Person')
    relation = models.CharField(max_length=26)

    class Meta:
        unique_together = ('student', 'parent')


class StudentParentProxy(StudentParent):
    class Meta:
        proxy = True  # << !!!!!!

【讨论】:

    猜你喜欢
    • 2021-11-26
    • 1970-01-01
    • 2012-12-04
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    相关资源
    最近更新 更多