首页 > 解决方案 > django m2m 关系真的有必要吗?

问题描述

所以我有两个这样的模型。

class Channel(BaseModel):
    class Meta:
        verbose_name = 'channel'
        verbose_name_plural = 'channels'
        indexes = [
            models.Index(fields=['box', 'name'], name='channel_box_name_idx'),
        ]

    def __str__(self):
        return self.name

    def get_next_position(self):
        aggregate = self.box.channels.aggregate(models.Max('position'))
        return (aggregate['position__max'] or -1) + 1

    def save(self, *args, **kwargs):
        if self._state.adding:
            # we insert the object's position if
            # it hasn't been created yet. We need to do
            # this explicitly because django doesn't
            # allow more than one auto-field
            self.position = self.get_next_position()
            super(Channel, self).save(*args, **kwargs)
            return self.box.channels.add(self)
        super(Channel, self).save(*args, **kwargs)

    objects = models.Manager()
    name = models.CharField(max_length=100, validators=[MinLengthValidator(2)])
    box = models.ForeignKey('api_backend.Box', on_delete=models.CASCADE)
    position = models.PositiveSmallIntegerField(db_index=True)

    REQUIRED_FIELDS = [name, box]

class Box(BaseModel):
    class Meta:
        verbose_name = 'box'
        verbose_name_plural = 'boxes'
        indexes = [
            models.Index(fields=['owner'], name='box_owner_idx'),
            models.Index(fields=['owner', 'name'], name='box_name_owner_idx'),
        ]

    def __str__(self):
        return self.name

    objects = models.Manager()
    icon = models.ImageField(upload_to='icons/', storage=DefaultStorage)
    name = models.CharField(max_length=100, validators=[MinLengthValidator(2)])
    owner = models.ForeignKey('api_backend.User', on_delete=models.CASCADE)
    channels = models.ManyToManyField('api_backend.Channel', related_name='box_channels')

    REQUIRED_FIELDS = [name, owner]

频道有一个属性box。并且 box 有一个 m2m 字段channels。所以在这种类型的关系中,每当我用盒子创建频道时,我都需要在盒子的 m2m 字段中添加相同的内容channels。这样的事情真的有必要吗?就像我需要为 m2m 字段提供一个额外的表,channels即使我没有它,我也可以通过执行来访问它box.channel_set

那么,性能会有什么变化吗?我应该改变我的模型结构吗?有人可以帮帮我吗?

标签: pythondjangodjango-models

解决方案


一个频道可以有多个盒子吗?如果是,则 aManyToManyField是合适的,ForeignKey应该删除

如果 aManyToManyField不是必需的,因为 aChannel只能有一个相关Box的,ManyToManyField则应删除 a 并使用相关的访问channel_set

如果您希望在Box实例上拥有一个名为channels而不是该属性的属性channel_set,则可以使用它来访问Channel您可以提供related_nameForeignKey

class Channel(BaseModel):
    ...
    box = models.ForeignKey('api_backend.Box', on_delete=models.CASCADE, related_name='channels')
    ...

推荐阅读