You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework(DRF)接口返回格式转换:列表转字典需求及实现问询

Django Rest Framework(DRF)接口返回格式转换:列表转字典需求及实现问询

看起来你现在遇到的问题是:DRF接口返回的是包含单个数据对象的列表格式,但你期望它能像原Java API那样直接返回单个字典对象,对吧?我来帮你梳理下问题原因和调整方案。

问题场景回顾

  • 当前DRF接口返回格式(列表包裹单条数据):
[{ "id": 1, "ind_id": 1, "co_ind": "Some String", "no_ind": "Some String", "ds_ind": "Some String", "ds_not_ind": "", "uni_id": 1, "per_id": [ { "id": 7, "no_per": "Some String", "tip_var": "", "co_per": "Some String", "no_cat": "", "per_id": 7, "uni_id": 1 }, { "id": 9, "no_per": "Some String", "tip_var": "", "co_per": "Some String", "no_cat": "", "per_id": 9, "uni_id": 1 }, ], "co_mod": "Some String" }]
  • 期望的Java API风格返回格式(直接返回单条数据字典):
{ "id": 1, "ind_id": 1, "co_ind": "A", "no_ind": "DOMÍCILIOS QUE POSSUEM EQUIPAMENTO TIC", "ds_ind": "Total de domicílios", "ds_not_ind": "", "uni_id": 1, "per_id": [ { "id": 7, "no_per": "Proporção de domicílios que possuem equipamentos TIC", "tip_var": "", "co_per": "DIC_TV", "no_cat": "", "per_id": 7, "uni_id": 1 }, { "id": 9, "no_per": "Proporção de domicílios que possuem equipamentos TIC", "tip_var": "", "co_per": "DIC_RADIO", "no_cat": "", "per_id": 9, "uni_id": 1 }, ], "co_mod": "A" }

问题原因

你用的ModelViewSet默认的list动作会把查询集(哪怕只有一条数据)当成集合来序列化,所以最终返回的是列表格式。你的自定义GetIndFilter过滤后返回的依然是QuerySet类型(即使只有一条数据),所以序列化后还是会被包裹成列表。

解决方案:重写视图的list方法

我们可以在GetIndViewSet里重写list方法,判断是否传入了ind_id参数,并且过滤后的结果只有一条数据,如果满足条件就直接返回单个对象的序列化结果,否则保持默认的列表返回逻辑。

修改后的views.py代码如下:

from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Inds
from .serializers import IndsSerializer

class GetIndViewSet(viewsets.ModelViewSet):
    queryset = Inds.objects.all()
    serializer_class = IndsSerializer

    # 简化原来的自定义Filter,直接在get_queryset里处理参数
    def get_queryset(self):
        queryset = super().get_queryset()
        ind_id = self.request.query_params.get('ind_id')
        if ind_id:
            queryset = queryset.filter(ind_id=ind_id)
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        ind_id = request.query_params.get('ind_id')
        
        # 当传入ind_id且结果只有一条时,返回单个对象
        if ind_id and queryset.count() == 1:
            serializer = self.get_serializer(queryset.first())
            return Response(serializer.data)
        
        # 其他情况保持默认的列表返回逻辑
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

额外优化点

  • 如果需要处理ind_id对应结果不存在的情况,可以在判断里加上queryset.exists(),返回404状态码或空字典:
if ind_id:
    if queryset.exists():
        if queryset.count() == 1:
            serializer = self.get_serializer(queryset.first())
            return Response(serializer.data)
        # 如果ind_id对应多条结果,依然返回列表
    else:
        # 返回404或空字典,根据需求调整
        return Response({}, status=status.HTTP_404_NOT_FOUND)
  • 原来的自定义GetIndFilter可以简化掉,直接用get_queryset处理参数更直观。

这样调整后,当你用requests.get(base_url + "get_ind?ind_id={}".format(ind))请求时,接口就会返回单个字典对象,和原Java API的格式一致了。

备注:内容来源于stack exchange,提问作者null92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:47:51