Django中如何获取多层多对一关联下每个Database的最新10条Result记录
首先请确保Result模型存在用于判断新旧的时间字段(例如created_at = models.DateTimeField(auto_now_add=True),以下方案均基于该字段做排序)。
实现方案
方案1:单Database实例查询(最简单,无需原生SQL)
如果仅需要查询单个Database对应的最新10条Result,直接用ORM跨关联过滤即可:
# 先获取目标Database实例 db = Database.objects.get(id=your_db_id) # 跨两层外键过滤,按创建时间倒序取前10条 latest_10_results = Result.objects.filter(result__data_base=db).order_by('-created_at')[:10]
方案2:批量查询所有Database的最新10条Result(高性能ORM实现,Django 3.2+支持)
如果需要一次性拿到所有Database各自对应的最新10条Result,用Django ORM的窗口函数即可实现,避免N+1查询问题:
from django.db.models import Window, F from django.db.models.functions import RowNumber # 给每条Result按所属Database分组、按创建时间倒序编号,只取每组前10条 filtered_results = Result.objects.annotate( row_num=Window( expression=RowNumber(), partition_by=F('result__data_base_id'), # 按DatabaseID分组 order_by=F('created_at').desc() # 按时间倒序排列 ) ).filter(row_num__lte=10).select_related('result', 'result__data_base') # 按Database分组整理结果 db_result_map = {} for res in filtered_results: db_obj = res.result.data_base if db_obj.id not in db_result_map: db_result_map[db_obj.id] = { "db_info": db_obj, "latest_results": [] } db_result_map[db_obj.id]["latest_results"].append(res)
方案3:低版本Django可使用原生SQL实现
如果使用的Django版本低于3.2不支持窗口函数,可以写原生SQL查询:
# 注意将yourapp替换为你的App实际名称 raw_query = """ SELECT r.* FROM yourapp_result r INNER JOIN yourapp_databasefieldstocheck df ON r.result_id = df.id WHERE ( SELECT COUNT(*) FROM yourapp_result r2 INNER JOIN yourapp_databasefieldstocheck df2 ON r2.result_id = df2.id WHERE df2.data_base_id = df.data_base_id AND r2.created_at >= r.created_at ) <=10 ORDER BY df.data_base_id, r.created_at DESC """ latest_results = Result.objects.raw(raw_query)
相关说明
- 无需强制使用原生SQL:只要Django版本在3.2及以上,纯ORM就能高效实现需求,可读性和可维护性更好。
- DTO不是必须选项:如果需要将结果返回给前端,直接用Django REST Framework的序列化器处理上述查询结果即可,仅当业务有复杂的字段封装、转换需求时才需要额外定义DTO。
内容的提问来源于stack exchange,提问作者dane4kq
相关产品推荐
相关产品推荐

