使用场景:
django查询数据库得到QuerySet A,对QuerySet A进行区分处理,并save保存;再查询另一条件得到QuerySet B,对QuerySet B进行区分处理,并save保存,最后想对QuerySet A 和QuerySet B合并,用于之后的统一处理操作。
常见的合并处理方式:
a|b 或 chain函数
方式1:
querysets = queryset_a | queryset_b
方式2:
from itertools import chain
querysets = chain(queryset_a, queryset_b)
缺陷说明:
方式1:
本着两个QuerySet合并,最终还想得到一个完整的大QuerySet,开始选择了a|b的形式,但是发现这种形式在当前场景存在问题。
a|b合并的思想类似于:
查询a时使用的sql语句 和 查询b时使用的sql语句 进行联合查询。如果上面查询到QuerySet a和b后,对a和b进行操作,并a.save(),b.save()保存,恰巧修改的字段为sql语句中的查询字段,那么a|b合并时,默认会使用之前a和b的sql语句联合查询,但是此时a和b已经通过.save进行字段修改了,那么查询出来的集合就为空,获取不对原始的结果了;如果在这个过程中,又创建了新的数据,并且新数据还满足上面的sql语句,那么查询结果可能为新增加的数据,并非原始的期望数据,出现问题。
所以: 对于较大的服务器,服务往往是并发或异步的,这样使用a|b进行数据合并,不论是自己save保持修改数据,还是并发创建新数据,合并的结果往往是错误的。需要慎重使用!
方式2:
使用chain函数得到的是迭代器,querysets = chain(queryset_a, queryset_b),因为是迭代器,对于querysets只能遍历使用1次,之后不会再有数据,可以使用list(querysets)进行转换,列表可以多次使用;但是还是没有得到最初期望的
QuerySet格式,最多set(list(querysets))得到个集合,没有太多意义。
总结:
最后使用chain进行数据合并,再通过list转化成列表,对于原始代码没有什么影响。