如何在Django REST Framework的GET请求中传递JSON参数?
解决方案:Django REST Framework GET传参或POST序列化问题
方案一:修复GET请求接收参数
GET请求的参数不在request.data中,而是存储在request.query_params里。对于列表类型的distincts_list,需要前端将其转为JSON字符串传递,后端再解析为列表。同时要加入参数合法性校验,避免无效查询。
步骤1:定义参数验证序列化器
from rest_framework import serializers class AlarmlogsFilterParamsSerializer(serializers.Serializer): column_name = serializers.CharField() distincts_list = serializers.ListField(child=serializers.CharField())
步骤2:修改GET视图
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status, permissions import json from .models import Alarmlog from .serializers import AlarmlogSerializer, AlarmlogsFilterParamsSerializer class GetAlarmlogsFilterByDistincts(APIView): permission_classes = (permissions.IsAuthenticated,) def get(self, request, *args, **kwargs): # 获取URL查询参数 params = request.query_params # 解析distincts_list的JSON字符串 try: distincts_list = json.loads(params.get('distincts_list', '[]')) except json.JSONDecodeError: return Response({"error": "distincts_list必须是合法的JSON数组"}, status=status.HTTP_400_BAD_REQUEST) # 构造验证数据并校验 validate_data = { 'column_name': params.get('column_name'), 'distincts_list': distincts_list } serializer = AlarmlogsFilterParamsSerializer(data=validate_data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) column_name = serializer.validated_data['column_name'] distincts_list = serializer.validated_data['distincts_list'] # 验证字段是否属于Alarmlog模型 if not hasattr(Alarmlog, column_name): return Response({"error": f"字段{column_name}不存在于Alarmlog模型"}, status=status.HTTP_400_BAD_REQUEST) # 优化查询:用__in一次获取所有符合条件的记录(替代多次filter) queryset = Alarmlog.objects.filter(**{f"{column_name}__in": distincts_list}) # 用自定义序列化器返回JSON对象 serialized_response = AlarmlogSerializer(queryset, many=True) return Response(serialized_response.data, status=status.HTTP_200_OK)
前端请求示例
GET /api/alarmlogs-filter/?column_name=severity&distincts_list=["low","high"]
方案二:修复POST请求的序列化问题
原POST代码的核心问题是使用了Django内置的serializers.serialize('json', ...),它返回的是JSON字符串,而DRF的Response会自动将Python对象序列化为JSON对象,应改用自定义的AlarmlogSerializer处理。
修改后的POST视图
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status, permissions from .models import Alarmlog from .serializers import AlarmlogSerializer, AlarmlogsFilterByDistinctsSerializer class AlarmlogsFilterByDistincts(APIView): permission_classes = (permissions.IsAuthenticated,) serializer_class = AlarmlogsFilterByDistinctsSerializer def post(self, request, *args, **kwargs): # 验证请求参数 serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) column_name = serializer.validated_data['column_name'] distincts_list = serializer.validated_data['distincts_list'] # 验证字段合法性 if not hasattr(Alarmlog, column_name): return Response({"error": f"字段{column_name}不存在于Alarmlog模型"}, status=status.HTTP_400_BAD_REQUEST) # 优化查询 queryset = Alarmlog.objects.filter(**{f"{column_name}__in": distincts_list}) # 用自定义序列化器序列化(many=True处理多条记录) response_serialized = AlarmlogSerializer(queryset, many=True) return Response(response_serialized.data, status=status.HTTP_200_OK)
说明
- 移除了
serializers.serialize('json', ...),改用自定义的AlarmlogSerializer(需确保该序列化器是继承自ModelSerializer的模型序列化器)。 - 将
CreateAPIView改为APIView,因为该接口是查询资源而非创建资源,更符合REST规范。
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

