【多对多】多对多取数无序的问题
orm 中的多对多插入数据,会按照插入顺序在中间表中创建数据
a 表通过关系字段查到所有的 b 对象,形如 a.filed.all() 此时查出的 b 对象是无序的,会按照 b 对象的创建顺序去除 如插入顺序为 1,7,2,6,11 取值时结果为 1,2,6,7,11 打乱了初始顺序
此时可以手动创建中间表来管理这部分关系
另外也可以使用 through 达到这种效果,而且不用多创建表
a.filed.through.objects.filter(arg=xxx).order_by('id').values_list('funcargs_id')
通过 through 可以获取 django 自建的第三张表,因为在顺序插入数据的时候,第三章表中的数据会自增,他的 id 可以作为顺序的参照,
通过第三张表获取到顺序之后,在通过自己的一些处理即可反推出 a.filed.all()中的对象顺序。
class FuncConfig(models.Model):
"""
任务处理函数配置
"""
func_id = models.AutoField(primary_key=True)
name = models.CharField('名称', max_length=50, null=False, blank=False)
func = models.CharField('函数', max_length=50, null=False, blank=False)
config_type = models.CharField('配置类型', choices=CONFIG_TYPE, max_length=64, default='FileConfig')
args = models.ManyToManyField(FuncArgs, verbose_name='接口参数', blank=True)
args_name = models.TextField('参数别名', blank=True, null=True)
args_index = models.CharField('参数顺序', max_length=512, null=True, blank=True)
def __str__(self):
return f"{self.name}"
class Meta:
verbose_name = '接口配置'
verbose_name_plural = '接口配置'
def get_args(self):
args_data = list(self.args.all().values())
for i in args_data:
source = get_source_data(i['source_data'])
i.update({'source_data': source, 'value': ''})
# 参数插入顺序
args_input_index = self.args_index.split(',')
# 第三方表中的参数 id 顺序
args_through_index = sorted(args_input_index)
data = []
if args_data:
name_list = self.args_name.split(',')
# 按照插入顺序
for index, input_index in enumerate(args_input_index):
item = args_data[args_through_index.index(input_index)]
# 引入参数别名
if name_list:
item['name'] = name_list[index]
data.append(item)
return data
# 在 每次 func 对象 save 的时候,会根据目前的顺序在 args_index 上记录
def save(self, force_insert=False, force_update=False, using=None, update_fields=None, *args, **kwargs):
args_input_id = self.args.through.objects.filter(funcconfig=self).order_by('id').values_list('funcargs_id')
self.args_index = ','.join([str(i[0]) for i in args_input_id])
super().save(*args, **kwargs)
2021-06-07 11:48:47 add 和 set 的区别
当多对多 set 的时候,django orm 有自己一套插入规则,顺序不会被保证,不论是 obj1.m2m.set(id_list) 还是 obj1.m2m.add(*[obj_list]) 顺序都是经过转化后的,如果要顺序的话,只能做 for 循环遍历,一个一个的 add(obj)