django - 在 Django 中的 M2M 关系上使用 'through' 参数的原因

标签 django django-users django-orm django-custom-user

简明问题:
在不使用 through 参数的情况下在外部表上对 Django (1.5) 中的多对多关系建模有哪些优点和缺点?

详情:
比如说,我有一个自定义用户模型 UserProfile,我想定义与同一模型的 m2m 关系,例如实现跟随 关系。我可以定义一个外部表(模型)like so :

class Relationship(models.Model):
    """Relationship model"""
    from_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='from_users')
    to_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='to_users')
    created = models.DateTimeField(auto_now_add=True)
    is_blocked = models.BooleanField(default=False)
    objects = RelationshipManager()

在这种情况下,我应该向 UserProfile 模型添加一个 m2m 字段,如下所示吗?如果是,为什么?我可以只使用 Relationship 模型处理用户之间的所有关系,不是吗?

class UserProfile(AbstractBaseUser, PermissionsMixin):
    user_following = models.ManyToManyField('self', through=Relationship, symmetrical=False, related_name='followed')

最佳答案

首先,重要的是要区分数据库中的概念数据模型 (CDM) 和物理数据模型 (PDM)。

从概念上讲,如果您想将一个 UserProfile 链接到另一个 UserProfile,似乎您需要 2 个实体。

但从技术上(物理上)来说,由于您正在创建多对多关系,您的系统绝对需要创建第三个数据库来存储您的 2 个 UserProfile 之间的关系,否则它不能!

请注意,如果它是 OneToOne 或 OneToMany 关系,从技术上讲,2 个表就足够了(这解释了为什么此关键字仅存在于 ManyToMany 关系中)。

现在,了解 Django 试图让您的生活更轻松:您可能不关心“物理”层。例如,如果您只想知道哪个用户连接到其他哪些用户,而没有其他信息。

-> 在那种情况下,您不关心第三个表,它只是使您的整个工作正常进行的技术限制!不需要使用 through 关键字。 在这种情况下,您在 Django 中只看到 2 个模型,但在数据库中有 3 个表,即使您在 Django 中看不到它。

但在某些情况下(通常实际上),您可以使用这第三个表来添加有关用户之间关系的重要信息。例如,如果您想存储关系创建的日期,那么第三个表就是完美的地方。

-> 这个“技术”表变成了“功能”表:您想直接在您的项目中使用它,因为它现在包含您需要的数据以及用户之间的关系! 是时候使用 through 关键字在 Django 项目中定义第三个表,并将属性(如 assocation_date)添加到此模型/表。 现在您在 Django 中有 3 个模型,数据库中还有 3 个表(带有您添加的附加属性)。

另一个经典例子

客户可以订购 1->N 种产品。一个产品可以被 0->N 个客户订购。这显然是多对多关系。

如果我想存储有关订单的信息(如总价、日期等),我可以在定义客户和产品之间的 M2M 关系时设置一个 through="Order" . 然后,我在 Django 中定义了 Order 模型,然后 bingo!

关于django - 在 Django 中的 M2M 关系上使用 'through' 参数的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24152102/

相关文章:

python - 自定义 django 用户模型不一致的迁移历史错误

Django自定义加载外键

python - Django 使用表达式聚合查询

django - 导入错误 : No module named local

Django:存储分层数据

Django 当循环查询集时,数据库读取何时发生?

python - 使用 Django ORM 作为跨主机的多进程锁

Django 获取内联表单管理员中的实例

python - 将现有模型迁移到 Django 内置用户模型

python - 具有多种共同属性的多种类型的用户