如何在Django 4 REST Framework中通过POST批量查询数据?
实现思路与代码修改方案
核心思路
通过在现有MediasViewSet中新增自定义POST动作来实现批量查询,核心是:
- 接收POST传入的数组格式请求数据
- 批量查询数据库(避免循环单查,提升性能)
- 按请求顺序匹配结果,存在则返回序列化数据,不存在则返回
null(符合JSON规范,对应Python的None)
具体代码修改
1. 修正序列化器的语法错误
你的MediaSerializer存在语法笔误,先修正:
class MediaSerializer(serializers.ModelSerializer): class Meta: model = Media fields = ['id', 'name', 'processed_status'] # 修正model和fields的分隔
2. 给MediasViewSet添加批量查询动作
在现有类中新增自定义POST接口,保留原有GET查询逻辑不受影响:
from rest_framework.decorators import action from rest_framework.response import Response from rest_framework import status class MediasViewSet(viewsets.ModelViewSet): queryset = Media.objects.all().order_by('name') serializer_class = MediaSerializer authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get_queryset(self, *args, **kwargs): # 保留原有GET单条查询逻辑 queryset = super().get_queryset() if "name" in self.request.data: query = self.request.data['name'] if query: queryset = Media.objects.filter(name=query) return queryset # 新增批量查询接口 @action(detail=False, methods=['post'], url_path='batch-check') def batch_check(self, request): # 校验请求格式:必须是数组 if not isinstance(request.data, list): return Response({"error": "请求数据必须是JSON数组"}, status=status.HTTP_400_BAD_REQUEST) # 提取所有待查询的name target_names = [item.get('name') for item in request.data] # 批量查询数据库,一次SQL查询搞定 existing_medias = Media.objects.filter(name__in=[name for name in target_names if name]) # 构建name到序列化数据的映射,方便快速匹配 media_map = {media.name: MediaSerializer(media).data for media in existing_medias} # 按请求顺序生成结果 result = [] for name in target_names: if not name: result.append(None) else: result.append(media_map.get(name, None)) return Response(result)
关键细节说明
- 接口路径:默认路由下,该批量接口的访问路径为
/medias/batch-check/ - 性能优化:用
name__in做批量查询,替代循环单查数据库,大幅减少SQL请求次数 - 顺序保证:严格按照请求数组的顺序返回结果,确保每个位置的结果对应原请求的条目
- 错误处理:校验请求格式,若传入非数组数据直接返回400错误
- 兼容性:原有GET单条查询逻辑完全保留,不影响现有功能
请求响应示例
请求(POST到/medias/batch-check/):
[ {"name": "media1"}, {"name": "media2"}, {"name": "media3"} ]
响应:
[ {"id": "xxx-xxx-xxx", "name": "media1", "processed_status": "xxx"}, null, {"id": "yyy-yyy-yyy", "name": "media3", "processed_status": "xxx"} ]
内容的提问来源于stack exchange,提问作者JOY
相关产品推荐
相关产品推荐

