代码之家  ›  专栏  ›  技术社区  ›  Jeflopo

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

  •  1
  • Jeflopo  · 技术社区  · 7 年前

    创建多对多关系时,我们使用中间表。假设我使用以下实体 video ,则, category ,则, tag VideoCategory ,则, VideoTag 建立关系。

    我假设许多标签/类别可以有许多视频,反之亦然。

    我用 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)
    

    现在 分类学 实体将持有 类别 标签 与视频相关,反之亦然。

    我加入了“null=True”,以便能够创建与没有标签的类别以及与没有标签但没有类别的标签的关系。

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

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

    这也意味着使用 分类学 这两个关系的实体可以有许多 NULL 其中一个字段 类别 标签 每个具体关系实例(行)上的字段均为空。

    问题:

    什么会更好?要使中间表保持独立(VideoCategory&VideoTag),还是将这些中间表合并到一个中间表中?(分类学)


    由于我缺乏数据库方面的经验,我不能说我是否遗漏了一些重要的东西。如果只使用一个中间表就可以在不久的将来出现问题或类似的情况。。。如果一切正常的话。

    1 回复  |  直到 4 年前
        1
  •  0
  •   albar    7 年前

    你必须使用 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'))