Django ORM如何对分组后的外键关联结果进行过滤查询
实现方案
你可以通过Subquery结合OuterRef的方式实现,最终直接拿到完整的Person类型QuerySet,代码如下:
from django.db.models import OuterRef, Subquery # 子查询:获取每个Person对应的最新Result记录的主键 latest_result_subq = Result.objects.filter( person_id=OuterRef("pk") ).order_by("-time").values("pk")[:1] # 外层查询:筛选符合条件的Person person_qs = Person.objects.filter( result__pk=Subquery(latest_result_subq), result__outcome__in=[2, 3] ).distinct()
方案说明
OuterRef("pk")用于引用外层查询中Person表的主键,实现子查询与外层表的关联- 子查询按
time字段倒序后取第一条,得到每个Person最新的Result记录主键 - 外层查询直接对
Person表做筛选,关联最新Result记录的同时过滤outcome值,最终返回的就是完整的PersonQuerySet,保留所有字段 - 末尾加
distinct()是为了避免关联查询产生重复的Person记录
替代方案(基于注解+F表达式)
如果你更习惯用分组注解的方式,也可以用以下写法:
from django.db.models import Max, F person_qs = Person.objects.annotate( latest_time=Max("result__time") ).filter( result__time=F("latest_time"), result__outcome__in=[2, 3] ).distinct()
注意事项
如果存在同一个Person同一时间有多条Result记录的情况,可以在子查询的排序规则中追加-id,确保每次只取唯一的最新记录:
latest_result_subq = Result.objects.filter( person_id=OuterRef("pk") ).order_by("-time", "-id").values("pk")[:1]
内容的提问来源于stack exchange,提问作者Ozzy
相关产品推荐
相关产品推荐

