使用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
相关产品推荐
相关产品推荐

