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

如何通过Django REST API实现分组查询并返回产品平均价格?

问题原因与解决方案

错误原因

你用values()+annotate()得到的是字典集合(ValuesQuerySet),而非Product模型实例。但你仍在使用ProductSerializer(继承自ModelSerializer),它默认会尝试访问模型实例的pk属性,字典没有这个属性,因此抛出AttributeError: 'int' object has no attribute 'pk'。

简洁解决方案

1. 定义专用序列化器

创建一个对应分组统计结果的序列化器,不需要依赖模型:

# serializers.py
from rest_framework import serializers

class ProductAveragePriceSerializer(serializers.Serializer):
    name = serializers.CharField()
    category = serializers.CharField()
    price_average = serializers.FloatField()

2. 更新视图配置

将视图的serializer_class替换为上面的专用序列化器,保持你的查询逻辑不变:

# views.py
from django.db.models import Avg
from rest_framework import generics, authentication, permissions

class ProductListAPIView(generics.ListAPIView):
    
    def get_queryset(self):
        # 假设params和query是你已处理好的请求参数
        queryset = Product.objects.filter(
            name=params['name'], 
            date__lte=query.date
        ).values('name','category').annotate(
            price_average=Avg('price')
        ).order_by()
        return queryset
    
    serializer_class       = ProductAveragePriceSerializer
    authentication_classes = [authentication.SessionAuthentication, authentication.TokenAuthentication]
    permission_classes     = [IsOwnerPermission]

可选:用APIView更灵活控制

如果需要更灵活的请求参数处理,改用APIView:

# views.py
from django.db.models import Avg
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions

class ProductAveragePriceAPIView(APIView):
    authentication_classes = [authentication.SessionAuthentication, authentication.TokenAuthentication]
    permission_classes     = [IsOwnerPermission]

    def get(self, request):
        # 从请求中获取参数
        name = request.query_params.get('name')
        date = request.query_params.get('date')
        if not name or not date:
            return Response({"error": "缺少name或date参数"}, status=400)
        
        queryset = Product.objects.filter(
            name=name, 
            date__lte=date
        ).values('name','category').annotate(
            price_average=Avg('price')
        ).order_by()
        serializer = ProductAveragePriceSerializer(queryset, many=True)
        return Response(serializer.data)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:50:22