如何用Django序列化器统计子表的数值总和与数量?
Django序列化器实现活动售票统计(总交易金额+总售票数)
修正后的完整代码
模型层(models.py)
from django.db import models from django.contrib.auth.models import User class Event(models.Model): name = models.CharField(max_length=100, null=False, blank=False) description = models.TextField(null=False, blank=False) date_time = models.DateTimeField() class EventTicket(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # 设置related_name,实现从Event反向查询关联的EventTicket event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='event_tickets') payment_status = models.SmallIntegerField(default=0, null=False, blank=False) # 1=支付成功,0=支付失败 total_amount = models.FloatField() date_time = models.DateTimeField()
序列化器层(serializers.py)
from rest_framework import serializers from django.db.models import Sum from .models import Event class EventTicketStatsSerializer(serializers.ModelSerializer): # 直接映射Event模型的id和name字段 event_id = serializers.IntegerField(source='id', read_only=True) event_name = serializers.CharField(source='name', read_only=True) # 自定义统计字段 total_transactions = serializers.SerializerMethodField() total_tickets = serializers.SerializerMethodField() class Meta: model = Event fields = ('event_id', 'event_name', 'total_transactions', 'total_tickets') def get_total_transactions(self, obj): # 过滤支付成功的记录,统计总金额,处理空值避免序列化报错 total = obj.event_tickets.filter(payment_status=1).aggregate(total=Sum('total_amount'))['total'] return total if total is not None else 0.0 def get_total_tickets(self, obj): # 统计当前活动的所有售票记录数 return obj.event_tickets.count()
视图层示例(views.py)
from rest_framework.response import Response from rest_framework.views import APIView from .models import Event from .serializers import EventTicketStatsSerializer class EventStatsView(APIView): def get(self, request): events = Event.objects.all() serializer = EventTicketStatsSerializer(events, many=True) return Response({ "ticket_details": serializer.data })
关键说明
- 反向查询基础:
EventTicket的event外键设置related_name='event_tickets',允许通过obj.event_tickets直接访问当前活动关联的所有售票记录。 - 字段映射:
event_id和event_name通过source参数直接绑定Event模型的原生字段,无需额外数据库查询。 - 总交易金额统计:通过
filter(payment_status=1)筛选支付成功的记录,使用Sum聚合函数计算金额总和,同时处理无符合条件记录时返回None的情况,转为0.0避免序列化错误。 - 总售票数统计:直接调用
count()方法统计当前活动关联的所有售票记录数量。
输出示例
"ticket_details": [ { "event_id": 1, "event_name": "Event-1", "total_transactions": 10000.0, "total_tickets": 24 }, { "event_id": 2, "event_name": "Event-2", "total_transactions": 10000.0, "total_tickets": 24 } ]
内容的提问来源于stack exchange,提问作者Animeartist
相关产品推荐
相关产品推荐

