python - 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
那么,性能会有什么变化吗?我应该改变我的模型结构吗?有人可以帮帮我吗?
解决方案
一个频道可以有多个盒子吗?如果是,则 aManyToManyField
是合适的,ForeignKey
应该删除
如果 aManyToManyField
不是必需的,因为 aChannel
只能有一个相关Box
的,ManyToManyField
则应删除 a 并使用相关的访问channel_set
器
如果您希望在Box
实例上拥有一个名为channels
而不是该属性的属性channel_set
,则可以使用它来访问Channel
您可以提供related_name
给ForeignKey
class Channel(BaseModel):
...
box = models.ForeignKey('api_backend.Box', on_delete=models.CASCADE, related_name='channels')
...
推荐阅读
- android - Android Horizontal Recyclerview 在滚动时显示多项选择
- javascript - 无法从响应获取中访问 JWT Web 令牌
- julia - 如何创建新的精灵应用程序?
- r - 根据数据框中的顺序创建颜色矢量列表
- bash - 分隔十进制数的整数和小数部分
- performance - Jmeter:将统计数据格式化为 HTML 报告中的逗号
- python - Python json.py 无法将字符串转换为字典
- java - 反射抛出 java.lang.IllegalStateException: zip 文件已关闭
- java - Apache Camel Java 8 支持
- css - chield flex-direction 行不起作用反应原生?