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

如何通过Django Rest Framework API返回单条记录?(many=False异常)

问题修复:DRF设置many=False返回空数据丢失字段

问题场景

我用Django Rest Framework写了个API,想返回单条费用记录。当前用many=True时能正常返回数组格式的单条数据,但改成many=False后,返回的是空数据,还丢了xid字段。

当前API代码:

class Expense_View_API(APIView):
    permission_classes = [IsAuthenticated, ]

    def get(self, request):
        param_xid = request.GET.get('id','')
        if param_xid != "":
            expenses_recordset = Expenses.objects.filter(xid=param_xid)
            serializer = Expenses_Serializer(expenses_recordset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response("BAD REQUEST: Missing 'id' Parameter", status=status.HTTP_400_BAD_REQUEST)

设置many=False后的错误返回:

{
    "xdate": null,
    "xseller": null,
    "xamount": null,
}

期望返回:

{
    "xid": 111,
    "xdate": "2021-02-15T00:00:00Z",
    "xseller": "Amazon",
    "xamount": "30.00",
}

序列化器和模型代码:

class Expenses_Serializer(serializers.ModelSerializer):
    class Meta:
        model = Expenses
        fields = ('xid', 'xdate', 'xseller', 'xamount')

class Expenses(models.Model):
    xid = models.AutoField(db_column='xID', primary_key=True)
    xdate = models.DateTimeField(db_column='xDate', blank=True, null=True)
    xseller = models.CharField(db_column='xSeller', max_length=50, blank=True, null=True)
    xamount = models.DecimalField(db_column='xAmount', max_digits=19, decimal_places=2, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'Expenses'
        app_label  = 'Expenses'

    def get_absolute_url(self):
        return reverse('model-detail-view', args=[str(self.id)])

    def __str__(self):
        return self.my_field_name

问题原因

filter()返回的是QuerySet对象(哪怕结果只有一条数据),而many=False要求传入的是单个模型实例,不是QuerySet。当你用单个实例的序列化方式去处理QuerySet时,DRF会尝试从QuerySet对象上读取xdate、xseller这些字段,显然QuerySet没有这些属性,所以返回null;而xid是模型的主键,QuerySet也没有这个属性,直接被忽略,所以返回结果里看不到它。

修复方案

1. 用get()替代filter()获取单个实例

因为xid是主键,唯一标识一条记录,直接用get(xid=param_xid)就能拿到单个模型实例,此时序列化不需要设置many=True(默认就是many=False)。

2. 处理记录不存在的异常

get()如果找不到对应记录会抛出DoesNotExist异常,需要捕获并返回404状态码,避免API报错。

修改后的API代码:

from django.core.exceptions import ObjectDoesNotExist

class Expense_View_API(APIView):
    permission_classes = [IsAuthenticated, ]

    def get(self, request):
        param_xid = request.GET.get('id','')
        if param_xid != "":
            try:
                # 用get获取单个实例,而不是filter返回QuerySet
                expense = Expenses.objects.get(xid=param_xid)
                serializer = Expenses_Serializer(expense)  # 默认many=False,可省略
                return Response(serializer.data, status=status.HTTP_200_OK)
            except ObjectDoesNotExist:
                return Response("Record not found", status=status.HTTP_404_NOT_FOUND)
        else:
            return Response("BAD REQUEST: Missing 'id' Parameter", status=status.HTTP_400_BAD_REQUEST)

测试结果

修改后调用API,就能返回符合预期的单条对象格式数据,包含完整的xid字段:

{
    "xid": 111,
    "xdate": "2021-02-15T00:00:00Z",
    "xseller": "Amazon",
    "xamount": "30.00",
}

内容的提问来源于stack exchange,提问作者SqueezeOJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:20:39