为什么我们使用Django中间模型?

时间:2017-07-29 17:45:12

标签: python django django-models

为什么我们使用中间模型? 我们不能在没有中间模型的情况下使用多对多关系吗?

2 个答案:

答案 0 :(得分:2)

M2M关系需要中间表。您可以详细了解M2M关系是什么以及它们需要中间表的原因(文章中称为联结表here

Django通过为您自动创建此intermediate table来抽象出来,除非您需要在其上添加自定义字段。如果您这样做,那么您可以通过覆盖through参数来定义它,如图所示here

以下是快速了解表格所需的原因enter image description here

答案 1 :(得分:0)

来源:https://www.geeksforgeeks.org/intermediate-fields-in-django-python/

假设您有两个具有多对多关系的模型,例如客户和产品。一个客户可以购买多种产品,一种产品可以被多个客户购买。

但是您可以拥有一些既不属于它们又不属于它们但对交易很重要的数据,例如:数量或日期。

数量和日期是存储在中介模型中的中介数据。

from django.db import models 
  
class Item(models.Model): 
    name = models.CharField(max_length = 128) 
    price = models.DecimalField(max_digits = 5, decimal_places = 2) 
  
    def __str__(self): 
        return self.name 
  
class Customer(models.Model): 
    name = models.CharField(max_length = 128) 
    age = models.IntegerField() 
    items_purchased = models.ManyToManyField(Item, through = 'Purchase') 
  
    def __str__(self): 
        return self.name 
  
class Purchase(models.Model): 
    item = models.ForeignKey(Item, on_delete = models.CASCADE) 
    customer = models.ForeignKey(Customer, on_delete = models.CASCADE) 
    date_purchased = models.DateField() 
    quantity_purchased = models.IntegerField()

当您购买产品时,您是通过购买模型进行的:客户 customerquantity_purchased 中购买了 item 数量的商品 date_purchased

购买模型是中间模型。

Django 文档 says

<块引用>

...如果要手动指定中介表,可以使用 通过选项来指定代表 您要使用的中间表。

在这种情况下,我们在 Customer 模型中有这一行,它定义了 through = 'Purchase'

中的中介模型
items_purchased = models.ManyToManyField(Item, through = 'Purchase')

现在让我们使用 Django Documentation 中的示例。

您有一个音乐家数据库,其中的音乐家与所属乐队存在多对多关系:一个音乐家可以属于多个乐队,而乐队可以有多个音乐家。

您想保留哪些数据?

对于音乐家(人):他们演奏的名字和乐器 对于乐队:名称和风格。

from django.db import models

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


class Group(models.Model):
    name   = models.CharField(max_length=128)
    style  = models.CharField(max_length=128)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    

但是,您不认为知道此人何时加入乐队很重要吗?什么模型最适合添加 date_joined 字段?将它添加到 Person 或 Group 是没有意义的,因为它不是每个人的固有字段,而是与一个动作有关:加入乐队。

所以你做了一个很小但很重要的调整。您创建一个中间模型,将 PersonGroup 与成员资格状态(包括 date_joined)相关联。

新版本是这样的:

from django.db import models

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


class Group(models.Model):
    name    = models.CharField(max_length=128)
    style   = 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()

变化是:

  1. 您添加了一个名为 Membership 的新类,它反映了会员状态。
  2. 在组模型中,您添加了 members = models.ManyToManyField(Person, through='Membership')。有了这个,您就可以将 PersonGroupMembership 联系起来,感谢 through

澄清一些重要的事情。

在多对多 (M2M) 关系中始终需要一个中间模型,或者用关系数据库术语来说,一个关联实体

<块引用>

关系数据库需要实现基本关系 (或基表)来解决多对多关系。基础关系 代表这种实体被非正式地称为关联 表...可以包含对同一数据库中相同或不同数据库表中的列的引用。

关联(或连接)表通过以下方式将两个或多个表映射到一起 引用每个数据表的主键。实际上,它 包含多个外键,每个外键都是多对一的关系 从连接表到单个数据表。 PK的 关联表通常由 FK 列本身组成。 (source)

Django 将创建中间模型,即使您没有使用 through 明确定义它。

<块引用>

在幕后,Django 创建了一个中间连接表来 表示多对多的关系。默认情况下,这个表名 是使用多对多字段的名称和 包含它的模型的表。

Django 会自动生成一张表来管理多对多 关系。但是,如果您想手动指定 中间表,您可以使用 through 选项指定 代表您想要的中间表的 Django 模型 采用。 此选项最常用于将额外数据与多对多关系相关联时。(source)