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

使用Django Prefetch对象异常:无法正确统计餐厅近一月销售额

解决Django中仅统计近一个月销售额的问题

你的问题出在Prefetch只是预取了近一个月的销售数据,但annotate聚合时并没有限定范围——Sum('sales__income')依然会计算该餐厅所有的销售额,不管时间。下面是两种可行的修复方案:

方案一:在Sum聚合中直接添加过滤条件

直接在Sum里用filter参数指定近一个月的时间范围,同时为了避免因多评分导致餐厅重复,加上distinct():

from django.db.models import Sum, Q

def index(request):
    month_ago = timezone.now() - timezone.timedelta(days=30)
    # 筛选有五星评分的餐厅,同时聚合近一个月的销售额
    restaurants = Restaurant.objects.filter(ratings__rating=5).distinct()\
        .annotate(
            total=Sum(
                'sales__income',
                filter=Q(sales__datetime__gte=month_ago),
                output_field=models.DecimalField()
            )
        )
    context = {'restaurants': restaurants}
    return render(request, 'index.html', context)

方案二:使用FilteredRelation关联过滤后的销售数据

先通过FilteredRelation定义一个仅包含近一个月销售的关联,再对这个关联进行聚合:

from django.db.models import Sum, FilteredRelation, Q

def index(request):
    month_ago = timezone.now() - timezone.timedelta(days=30)
    restaurants = Restaurant.objects.filter(ratings__rating=5).distinct()\
        .annotate(
            monthly_sales=FilteredRelation(
                'sales',
                condition=Q(sales__datetime__gte=month_ago)
            )
        )\
        .annotate(
            total=Sum('monthly_sales__income')
        )
    context = {'restaurants': restaurants}
    return render(request, 'index.html', context)

关键说明

  • distinct()必须加:因为filter(ratings__rating=5)会让有多个五星评分的餐厅重复出现在结果里,distinct()用来去重。
  • 两种方案都能精准统计近一个月的销售额,区别是方案一更简洁,方案二更适合需要多次使用过滤后关联的场景。

内容的提问来源于stack exchange,提问作者Sibi K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:42:42