为何对Django QuerySet按有效pk筛选时返回完整数据集?
问题根因
你触发了Django ORM跨一对多关联查询的重复结果问题:
- 你通过
synonyms__name__icontains反向关联查询Compound时,ORM会自动执行Compound表和Synonym表的JOIN操作 - 同一个Compound如果有N个符合筛选条件的Synonym,JOIN后的结果集就会生成N条对应该Compound的记录,ORM会把这N条记录实例化为N个相同pk的Compound对象,所以你会看到QuerySet里全是同一个化合物的重复条目
- 你后续对该QuerySet执行
filter(pk=pk)时,是在已经生成的JOIN结果集上做筛选,而结果集里所有条目都是这个pk的Compound,自然会返回全部重复结果,调用get()也会因为匹配到多条结果抛出MultipleObjectsReturned异常
解决方法
在首次构造QuerySet时添加distinct()去重即可,保证每个Compound实例唯一:
set_synonyms = Compound.objects.filter(synonyms__name__icontains=query_string).distinct()
调整后QuerySet里不会再有重复的同pk对象,后续的filter(pk=pk)和get(pk=pk)操作都会正常生效。
额外说明
如果你的查询场景只需要判断某个pk是否符合原筛选条件,也可以直接基于原表做组合筛选,不需要复用带重复的QuerySet:
# 判断pk为76的化合物是否有符合条件的同义词 is_match = Compound.objects.filter(pk=76, synonyms__name__icontains=query_string).exists()
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

