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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:55:34