Django M2M 关系:只使用一个中介 table 还是每个实体对一个?
Django M2M relationships: Use just one intermediary table or one per entity pair?
在创建多对多关系时,我们使用中介 table。假设我使用以下实体 video
、category
、tag
和 VideoCategory
、VideoTag
来创建关系。
我假设许多 tags/categories 可以有很多视频,反之亦然。
我用 through
关键字来做,因为我希望将来可以使用额外的字段。
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='VideoCategory')
tags = models.ManyToManyField(Tag, through='VideoTag')
def __str__(self):
return self.title
class VideoCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
class VideoTag(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
但我想知道是否可以创建一个 taxonomy
实体并从一个地方处理与类别和标签的关系。
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy')
tags = models.ManyToManyField(Tag, through='Taxonomy')
def __str__(self):
return self.title
class Taxonomy(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, null=True)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
现在 taxonomy
实体将包含与视频相关的 category
和 tag
,反之亦然。
我添加了 'null=True' 以便能够与没有标签的类别和有标签但没有类别的关系建立关系。
如果我不使用它。我收到一个错误:
# sqlite3.IntegrityError: NOT NULL constraint failed: MyApp_taxonomy.category_id
这也意味着,如果这些 category
或 tag
字段之一为空,则将单个 taxonomy
实体用于两个关系可能有许多 NULL
字段每个具体关系实例(行)。
问题:
什么会更好?保持中介 table 独立(VideoCategory & VideoTag)或将这些中介 table 合二为一? (分类)
由于我缺乏数据库方面的经验,所以我不能说我是否遗漏了一些重要的东西。如果只与一个中间人一起做 table 会在不久的将来出现问题或类似的事情......如果它就好了。
您必须使用 through_fields
参数 (doc):
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy', through_fields=('video', 'category'))
tags = models.ManyToManyField(Tag, through='Taxonomy', through_fields=('video', 'tag'))
在创建多对多关系时,我们使用中介 table。假设我使用以下实体 video
、category
、tag
和 VideoCategory
、VideoTag
来创建关系。
我假设许多 tags/categories 可以有很多视频,反之亦然。
我用 through
关键字来做,因为我希望将来可以使用额外的字段。
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='VideoCategory')
tags = models.ManyToManyField(Tag, through='VideoTag')
def __str__(self):
return self.title
class VideoCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
class VideoTag(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
但我想知道是否可以创建一个 taxonomy
实体并从一个地方处理与类别和标签的关系。
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy')
tags = models.ManyToManyField(Tag, through='Taxonomy')
def __str__(self):
return self.title
class Taxonomy(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, null=True)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
现在 taxonomy
实体将包含与视频相关的 category
和 tag
,反之亦然。
我添加了 'null=True' 以便能够与没有标签的类别和有标签但没有类别的关系建立关系。
如果我不使用它。我收到一个错误:
# sqlite3.IntegrityError: NOT NULL constraint failed: MyApp_taxonomy.category_id
这也意味着,如果这些 category
或 tag
字段之一为空,则将单个 taxonomy
实体用于两个关系可能有许多 NULL
字段每个具体关系实例(行)。
问题:
什么会更好?保持中介 table 独立(VideoCategory & VideoTag)或将这些中介 table 合二为一? (分类)
由于我缺乏数据库方面的经验,所以我不能说我是否遗漏了一些重要的东西。如果只与一个中间人一起做 table 会在不久的将来出现问题或类似的事情......如果它就好了。
您必须使用 through_fields
参数 (doc):
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy', through_fields=('video', 'category'))
tags = models.ManyToManyField(Tag, through='Taxonomy', through_fields=('video', 'tag'))