You need to enable JavaScript to run this app. Django Rest Framework聚合后自定义字段返回及序列化问题
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework聚合后自定义字段返回及序列化问题

问题根因
  • 核心逻辑错配:现有TransactionSerializer是绑定Transactions模型的ModelSerializer,适配单条模型实例的字段结构,和当前聚合查询返回的字典集合(仅包含vendor、a、b三个自定义字段)完全不匹配。
  • 序列化报错来源:聚合生成的b字段是Sum(amount)的计算结果,类型为Decimal,没有对应序列化规则的情况下会触发类型不兼容报错。
实现步骤

1. 新建适配聚合结果的序列化器

不要复用原有绑定模型的TransactionSerializer,在serializer.py中新增专门处理聚合结果的序列化类,明确声明每个字段的类型,同时用DRF自带的DecimalField处理Decimal类型的聚合值,从根源解决序列化问题:

from rest_framework import serializers

class SmartStatsSerializer(serializers.Serializer):
    # 对应values查询中的vendor字段
    vendor = serializers.CharField()
    # 对应annotate中Count生成的a字段
    a = serializers.IntegerField()
    # 对应annotate中Sum生成的b字段,直接用DecimalField适配数值类型
    b = serializers.DecimalField(max_digits=19, decimal_places=2)

此处使用基础Serializer而非ModelSerializer,因为聚合结果不绑定具体模型实例,无需走模型字段自动映射逻辑。

2. 修改视图类的序列化器绑定

把视图类中原有绑定的TransactionSerializer替换为新建的聚合结果序列化器:

class smarts(generics.ListAPIView):
    # 替换为适配聚合结果的序列化器
    serializer_class = SmartStatsSerializer
    permission_classes = [permissions.IsAuthenticated, TransactionIsOwnerOrNot]

3. 完善get_queryset的返回逻辑

你之前编写的聚合查询本身逻辑正确,不需要额外做手动JSON编码处理,直接返回该查询集即可——DRF的ListAPIView会自动将查询集(包括.values()生成的字典集合)传给绑定的序列化器完成序列化,最终输出符合要求的JSON响应:

def get_queryset(self):
        card = get_object_or_404(self.request.user.cards, pk=self.kwargs['pk'])
        # 聚合查询逻辑保持原有实现不变
        qs = card.transactions.values('vendor').annotate(
            a=Count('pk'),
            b=Sum('amount')
        ).order_by('-b')
        # 直接返回构造好的查询集即可
        return qs
注意事项
  • 无需额外手动调用DjangoJSONEncoder,DRF序列化器已内置对Decimal类型的完整支持,只要匹配对应字段类型,即可正常序列化输出。
  • 不推荐直接修改原有TransactionSerializer的字段定义来适配聚合需求,会导致原有绑定模型的序列化器被污染,影响其他使用该序列化器的接口功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 21:54:05