如何通过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
相关产品推荐
相关产品推荐

