Django M2M 关系:只使用一个中介 table 还是每个实体对一个?

Django M2M relationships: Use just one intermediary table or one per entity pair?

在创建多对多关系时,我们使用中介 table。假设我使用以下实体 videocategorytagVideoCategoryVideoTag 来创建关系。

我假设许多 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 实体将包含与视频相关的 categorytag,反之亦然。

我添加了 'null=True' 以便能够与没有标签的类别和有标签但没有类别的关系建立关系。

如果我不使用它。我收到一个错误:

# sqlite3.IntegrityError: NOT NULL constraint failed: MyApp_taxonomy.category_id

这也意味着,如果这些 categorytag 字段之一为空,则将单个 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'))