Django REST API关联表场景下如何优化多轮GET拉取关联数据的方案
关联表接口调用优化方案
核心思路
通过开放明细接口的批量过滤能力,将原有的N次单条关联查询压缩为1次(或少量几次)批量查询,服务端不做任何主从数据拼接逻辑,数据整合完全由外部调用方完成,符合需求约束。
服务端改动(仅开放过滤能力,无硬编码聚合)
1. 集成官方过滤组件
使用DRF官方配套的django-filter组件实现批量过滤,无需手写自定义过滤逻辑:
- 安装依赖:
pip install django-filter - 在项目
settings.py中注册应用:
INSTALLED_APPS = [ # ... 其他已注册应用 'django_filters', ]
2. 配置明细接口的过滤规则
仅需修改VarsResults对应的视图集,开放id_res字段的批量过滤能力,完全不改动原有接口的返回结构,也不添加任何聚合逻辑:
from django_filters.rest_framework import DjangoFilterBackend from rest_framework import viewsets from .models import VarsResults from .serializers import VarsResultsSerializer class VarsResultsViewSet(viewsets.ReadOnlyModelViewSet): # 按你现有视图的继承类调整 serializer_class = VarsResultsSerializer # 原有查询、权限、分页等配置完全保留 queryset = VarsResults.objects.all() # 新增过滤后端配置 filter_backends = [DjangoFilterBackend] # 开放id_res字段的过滤,自动兼容单值/多值批量匹配 filterset_fields = ['id_res']
注:原有单条
id_res查询(如GET /results_details/?id_res=236)的行为完全不变,不会破坏现有调用逻辑。
如果不想引入django-filter依赖,也可以在原有视图中手写极简过滤逻辑,同样无聚合逻辑:
from rest_framework.views import APIView from rest_framework.response import Response from .models import VarsResults from .serializers import VarsResultsSerializer class VarsResultsListView(APIView): def get(self, request): # 解析传入的id_res参数,支持逗号分隔多值 id_res_param = request.query_params.get('id_res', '') id_res_list = [int(id) for id in id_res_param.split(',') if id.isdigit()] # 按批量id过滤,无任何数据拼接逻辑 queryset = VarsResults.objects.filter(id_res__in=id_res_list) if id_res_list else VarsResults.objects.none() serializer = VarsResultsSerializer(queryset, many=True) return Response(serializer.data)
外部调用方的整合流程
完全由调用方自主完成数据拼接,无服务端耦合:
- 按原逻辑调用主结果接口,通过
device字段筛选目标设备的结果列表,提取所有主结果的id值组成列表res_id_list = [175194, 21278, 25173, ...] - 拼接批量查询参数,一次性请求所有关联明细:
GET /api/results_details/?id_res=175194,21278,25173,... - 调用方拿到明细列表后,自行按
id_res字段分组,将明细匹配到对应的主结果记录中,完成数据整合。
特殊场景兼容
如果单次返回的主结果数量过多,导致URL查询参数长度超限,可按每100~200个ID为一批拆分多次请求,相比原有的单条调用效率仍有数量级提升。
性能保障:现有
VarsResults模型已为id_res字段建立联合索引,批量过滤的数据库查询会命中索引,无明显性能损耗。
内容的提问来源于stack exchange,提问作者Manuel Santi
相关产品推荐
相关产品推荐

