如何在Django中通过Prefetch按date分组聚合sum_weight?
解决方案
方法一:数据库层面分组(推荐,性能更优)
通过在Prefetch的查询集中使用values()按date分组,结合annotate()计算每日权重总和,同时用to_attr存储分组结果避免覆盖原关联数据。
修改查询代码:
groups = Group.objects.prefetch_related( Prefetch( "facts", queryset=Facts.objects.values('date').annotate(sum_weight=Sum('weight')).order_by('date'), to_attr='grouped_facts' ) )
修改序列化器:
因为grouped_facts是字典列表而非Facts实例,所以将GraphDot改为基础Serializer,并指定数据源为grouped_facts:
class GraphDot(serializers.Serializer): date = serializers.DateField() sum_weight = serializers.IntegerField() class FoodGraphSerializer(serializers.ModelSerializer): dots = GraphDot(many=True, source="grouped_facts") class Meta: model = Group fields = ("title", "dots") read_only_fields = ("title", "dots")
方法二:Python层面分组(适合小数据量场景)
如果不想调整数据库查询逻辑,可以在序列化器中通过Python代码完成分组汇总:
修改序列化器:
class FoodGraphSerializer(serializers.ModelSerializer): dots = serializers.SerializerMethodField() def get_dots(self, obj): # 按日期分组累加权重 date_weight_map = {} for fact in obj.facts.all(): date_key = fact.date.strftime('%Y-%m-%d') date_weight_map[date_key] = date_weight_map.get(date_key, 0) + fact.weight # 转换为要求的结构并按日期排序 return sorted( [{"date": date, "sum_weight": total} for date, total in date_weight_map.items()], key=lambda item: item["date"] ) class Meta: model = Group fields = ("title", "dots") read_only_fields = ("title", "dots")
简化查询代码:
此时无需在查询中annotate,直接预取关联数据即可:
groups = Group.objects.prefetch_related("facts")
内容的提问来源于stack exchange,提问作者COSHW
相关产品推荐
相关产品推荐

