【问题标题】:Why use "through" argument for ManyToManyField in Django models?为什么在 Django 模型中为 ManyToManyField 使用“through”参数?
【发布时间】:2012-02-08 01:24:43
【问题描述】:

查看 Django 文档并尝试找出“through”参数的用法。这是doc的链接。

例子:

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

    def __unicode__(self):
        return self.name

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

    def __unicode__(self):
        return self.name

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

为什么还需要 Group 的“members”属性? Membership 的“组”外键是否足以遵循关系并访问该信息?

【问题讨论】:

    标签: django django-models many-to-many django-orm


    【解决方案1】:

    我认为你在这方面的想法有点过于字面意思了。假设您没有使用through

    class Person(models.Model):
        name = models.CharField(max_length=128)
    
        def __unicode__(self):
            return self.name
    
    class Group(models.Model):
        name = models.CharField(max_length=128)
        members = models.ManyToManyField(Person)
    
        def __unicode__(self):
            return self.name
    

    Django 在幕后为您创建了以下模型:

    class GroupPerson(models.Model)
        group = models.ForeignKey(Group)
        person = models.ForeignKey(Person)
    

    创建Membership 模型的原因是添加默认模型 Django 自动 创建的默认模型没有的额外数据,但是由于您不再使用默认模型,因此您必须使用through 告诉 Django。基本上,您保留了 Django 为 ManyToManyFields 提供的 API。

    【讨论】:

      【解决方案2】:

      这样做的原因是 Group 有一个用于这种关系的字段,而不是必须通过它的 members_set 跟踪关系。

      如果没有别的,这可以使编写查询更简单。至少,这可以使程序员的生活更轻松,代码更易于阅读。一个充分优化的 ORM 将能够生成适当的索引来加速这种访问(除非我错了,django 确实这样做了;或者至少 South 这样做了)。

      【讨论】:

      • 这样会提高效率吗?还是只是为了方便?
      【解决方案3】:

      这样,您就可以从 Group 中直接访问成员。您不一定要直接处理 Membership 对象(用户甚至从未见过它们)。您只需要存储一些额外信息的组。将成员资格视为有关个人和组之间关联的元数据。

      【讨论】:

      • 但是将成员存储为组中的多对多而不需要遵循与成员资格的向后关系有什么区别?
      • 我想我真正的问题是,为什么我不想直接处理 Membership 对象?
      • 因为您通常会根据用户的某些操作来处理 Person 对象或 Group 对象。 Membership 对象很可能只是您偶尔会显示的一些数据,但不会是您在视图/模板之间传递的东西。
      【解决方案4】:

      通过表用于存储关系的属性,在这种情况下,例如Person 加入特定 Group 的日期

      【讨论】:

        猜你喜欢
        • 2020-08-09
        • 2011-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2020-05-11
        相关资源
        最近更新 更多