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

Django REST Framework中get_queryset返回单值/单行报错问题

DRF get_queryset 返回单行数据报错的解决办法

为啥会报错?

get_queryset 必须返回可遍历的对象(比如Django的QuerySet、Python列表),你直接返回单个StockPriceModel实例或者last_price这种float值,视图要遍历结果序列化时自然会报“not iterable”——人家要的是可迭代的集合,你给了单个值/对象,当然不行。

完整代码示例

from rest_framework import viewsets
from .models import StockPriceModel
from .serializers import StockPriceSerializer

class StockPriceViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = StockPriceSerializer

    def get_queryset(self):
        user = self.request.user
        # 从请求参数中获取指定的ticker(假设通过query_params传递)
        ticker = self.request.query_params.get('ticker')

        if user.is_superuser:
            # 超级用户:按ticker去重返回,PostgreSQL直接支持distinct('ticker')
            return StockPriceModel.objects.all().distinct('ticker')
            # 兼容MySQL的写法:取每个ticker的最新时间记录
            # latest_records = StockPriceModel.objects.values('ticker').annotate(latest_time=Max('timestamp'))
            # return StockPriceModel.objects.filter(
            #     ticker__in=[item['ticker'] for item in latest_records],
            #     timestamp__in=[item['latest_time'] for item in latest_records]
            # )
        else:
            if not ticker:
                # 未传ticker时返回空集合,也可根据业务需求抛出异常
                return StockPriceModel.objects.none()
            # 未认证用户:返回指定ticker的最新一行,用[:1]返回含单个对象的QuerySet(可迭代)
            return StockPriceModel.objects.filter(ticker=ticker).order_by('-timestamp')[:1]
            # 另一种写法:拿到单个实例后包装成列表
            # try:
            #     latest_obj = StockPriceModel.objects.filter(ticker=ticker).latest('timestamp')
            #     return [latest_obj]
            # except StockPriceModel.DoesNotExist:
            #     return []

关键修复点

  • 超级用户去重逻辑:用distinct('ticker')(PostgreSQL)或annotate取最新记录的方式,确保返回的是可迭代的QuerySet。
  • 未认证用户返回单行:
    • 别用.get()、.last()、.latest()直接返回单个实例,这些都不可迭代;
    • 优先用.order_by('-timestamp')[:1]返回仅含一条数据的QuerySet,既能满足可迭代要求,还能保留QuerySet的延迟加载等特性;
    • 若必须用.latest()获取单个实例,一定要把它放进列表(比如[latest_obj]),转换成可迭代结构;
    • 直接返回last_price这个float值是错误的,要么返回包含该值的模型实例,要么通过重写视图方法单独处理字段返回。

若仅需返回last_price字段

如果未认证用户只需要last_price而非完整模型数据,可以重写视图的list方法:

from rest_framework.response import Response

def list(self, request, *args, **kwargs):
    queryset = self.get_queryset()
    if not request.user.is_superuser and queryset.exists():
        return Response({'last_price': queryset[0].last_price})
    # 超级用户走正常的列表序列化逻辑
    return super().list(request, *args, **kwargs)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:15:13