使用直通模型

时间:2016-06-06 05:52:34

标签: django django-models

我无法理解使用直通模型使用ManyToMany模型字段。没有ManyToMany字段,我可以很容易地实现相同的功能。考虑以下Django的文档:

class Person(models.Model):
    name = models.CharField(max_length=128)


class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')


class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

我不明白,如何使用ManyToMany字段比简单地删除它并使用相关管理器更好。例如,这两个模型将更改为以下内容:

class Group(models.Model):
    name = models.CharField(max_length=128)


class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='members')
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

我在这里缺少什么?

2 个答案:

答案 0 :(得分:9)

是的,使用明确的through表基本上不需要ManyToManyField

拥有它的唯一真正好处是,如果您发现相关经理方便。就是这样:

group.members.all()  # Persons in the group

看起来比这更好:

Person.objects.filter(membership_set__group=group)  # Persons in the group

在实践中,我认为两者兼顾的主要原因是人们常常以简单的ManyToManyField开始;意识到他们需要一些额外的数据并添加一个through表;然后由于使用两个管理器的代码而导致两者都结束。

答案 1 :(得分:0)

我对凯文·克里斯托弗·亨利 (Kevin Christopher Henry) 的回答有疑问。

我不认为没有 group.members.all()through="members" 等价物是 Person.objects....

相反,如果 M2M 字段在 group.person_set.all() 侧,我认为它是 Person。或者 group.persons.all() 如果 M2M 字段在 Group 内。

但我认为没有 through=.. 你无法控制创建的表。它包含并将仅包含 2 个字段:相关行的两个 ID。

但是使用 through=..,您可以自己创建模型并添加(现在或以后)附加字段,这通常是有充分理由的。此类字段的示例:valid_from = DateField() 左右。