如何通过单次Django ORM查询获取所有选项对应的最新MachineOption对象
完全可以通过单次查询实现,不需要为每个选项单独发起请求,以下是几种常用实现方案:
方案1:使用Window窗口函数(通用方案,兼容大部分现代数据库)
Django 2.0及以上版本支持窗口函数,可实现按name、machine分组后取每组时间最新的记录,兼容MySQL 8+、PostgreSQL、SQLite 3.25+等主流数据库。
代码示例:
from django.db.models import F, Window from django.db.models.functions import Rank # 按名称+机器分组,取每组最新的记录 latest_options = MachineOption.objects.annotate( rank=Window( expression=Rank(), # 如果不需要区分机器,可去掉partition_by中的F('machine') partition_by=[F('name'), F('machine')], order_by=F('date_time').desc() ) ).filter(rank=1)
如果同组下存在多条完全相同date_time的记录,上述代码会全部返回,若仅需返回1条,把Rank()替换为RowNumber()即可。
方案2:PostgreSQL专属的distinct简化写法
如果你使用PostgreSQL作为数据库,可以利用其特有的DISTINCT ON语法,写法更简洁:
# 先按名称、机器正序,再按时间倒序,distinct会保留每组的第一条记录 latest_options = MachineOption.objects.order_by( 'name', 'machine', '-date_time' ).distinct('name', 'machine')
方案3:兼容低版本数据库的实现
如果使用MySQL 5.x等不支持窗口函数的数据库,可通过子查询+条件聚合实现:
from django.db.models import Max, Q # 先查询每个分组的最新时间 latest_time_map = MachineOption.objects.values('name', 'machine').annotate( latest_time=Max('date_time') ) # 构造查询条件 query_cond = Q() for item in latest_time_map: query_cond |= Q( name=item['name'], machine=item['machine'], date_time=item['latest_time'] ) latest_options = MachineOption.objects.filter(query_cond)
内容的提问来源于stack exchange,提问作者darkvodka
相关产品推荐
相关产品推荐

