Django多对多字段查询问题:如何仅获取属于群组的Person ID?
解决方法:筛选出属于任意群组的Person ID
首先得说清楚你原来的代码为什么没达到预期:select_related()这个方法是用来预加载外键/一对一关联的对象,它的作用是减少数据库查询次数,根本不会帮你过滤数据。所以不管有没有群组关联,它都会返回所有Person的ID,这就是问题所在。
要实现“仅获取属于任意群组的Person ID”,你需要用过滤条件来筛选掉那些没有加入任何群组的Person,这里有两种靠谱的方法:
方法一:反向关联过滤 + 去重
利用group_members这个反向关联(你在ManyToMany里定义的related_name),直接过滤掉关联为空的Person:
p = Persons.objects.filter(group_members__isnull=False).values('id').distinct()
group_members__isnull=False:确保当前Person至少属于一个群组distinct():因为一个Person可能加入多个群组,这一步是避免返回重复的ID
方法二:EXISTS子查询(更高效)
如果你的数据量比较大,用Exists子查询会更高效,它不会返回重复数据,也不需要额外去重:
from django.db.models import Exists, OuterRef p = Persons.objects.filter( Exists(Group.objects.filter(members=OuterRef('pk'))) ).values('id')
这个写法会生成一个数据库层面的EXISTS查询,检查是否存在包含当前Person的群组,逻辑清晰且性能更好。
另外补充一句:如果之后你需要预加载Person对应的群组数据(而不是过滤),那应该用prefetch_related('group_members'),而不是select_related——毕竟select_related只支持外键和一对一关系,处理不了多对多。
内容的提问来源于stack exchange,提问作者user12189424
相关产品推荐
相关产品推荐

