【多对多】多对多取数无序的问题

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)