为什么我们使用中间模型? 我们不能在没有中间模型的情况下使用多对多关系吗?
答案 0 :(得分:2)
M2M关系需要中间表。您可以详细了解M2M关系是什么以及它们需要中间表的原因(文章中称为联结表)here:
Django通过为您自动创建此intermediate table来抽象出来,除非您需要在其上添加自定义字段。如果您这样做,那么您可以通过覆盖through
参数来定义它,如图所示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()
当您购买产品时,您是通过购买模型进行的:客户 customer
在 quantity_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 是没有意义的,因为它不是每个人的固有字段,而是与一个动作有关:加入乐队。
所以你做了一个很小但很重要的调整。您创建一个中间模型,将 Person
、Group
与成员资格状态(包括 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()
变化是:
Membership
的新类,它反映了会员状态。members = models.ManyToManyField(Person, through='Membership')
。有了这个,您就可以将 Person
和 Group
与 Membership
联系起来,感谢 through
。在多对多 (M2M) 关系中始终需要一个中间模型,或者用关系数据库术语来说,一个关联实体。
<块引用>关系数据库需要实现基本关系 (或基表)来解决多对多关系。基础关系 代表这种实体被非正式地称为关联 表...可以包含对同一数据库中相同或不同数据库表中的列的引用。
关联(或连接)表通过以下方式将两个或多个表映射到一起 引用每个数据表的主键。实际上,它 包含多个外键,每个外键都是多对一的关系 从连接表到单个数据表。 PK的 关联表通常由 FK 列本身组成。 (source)
Django 将创建中间模型,即使您没有使用 through
明确定义它。
在幕后,Django 创建了一个中间连接表来 表示多对多的关系。默认情况下,这个表名 是使用多对多字段的名称和 包含它的模型的表。
Django 会自动生成一张表来管理多对多
关系。但是,如果您想手动指定
中间表,您可以使用 through
选项指定
代表您想要的中间表的 Django 模型
采用。
此选项最常用于将额外数据与多对多关系相关联时。(source)