Django中如何按年份统计指定Tourist的所有Arrival记录?
Django按年份统计指定游客的抵达记录问题
模型定义
class Tourist(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class Etablissement(models.Model): name = models.CharField(max_length=30) class Arrival(models.Model): tourist = models.ForeignKey(Tourist, on_delete=models.CASCADE) place = models.ForeignKey(Etablissement, on_delete=models.CASCADE) # 注:原模型需包含arrival_date字段,否则无法按年份分组
需求与错误场景
需要统计指定Tourist的所有Arrival记录并按年份分组,尝试的代码如下:
def detailTourist(request, id): touriste = Tourist.objects.get(id=id) datas = Arrival.objects.annotate(year=TruncYear('arrival_date')).values('year').annotate(total=Arrival.objects.filter(tourist=touriste)).order_by()
运行后出现错误:sub-select returns 19 columns - expected 1,原因是第二个annotate中直接传入了完整的Arrival查询集,而annotate需要的是聚合函数(如统计数量的Count),而非全字段的查询结果。
正确实现方式
方式一:先过滤再分组统计
from django.db.models import Count from django.db.models.functions import TruncYear def detailTourist(request, id): touriste = Tourist.objects.get(id=id) # 先筛选当前游客的抵达记录,再按年份分组统计数量 datas = Arrival.objects.filter(tourist=touriste)\ .annotate(year=TruncYear('arrival_date'))\ .values('year')\ .annotate(total=Count('id'))\ .order_by('year')
方式二:通过反向关联查询
利用Django的反向关联特性(touriste.arrival_set)直接获取该游客的所有抵达记录,再进行分组统计:
from django.db.models import Count from django.db.models.functions import TruncYear def detailTourist(request, id): touriste = Tourist.objects.get(id=id) datas = touriste.arrival_set\ .annotate(year=TruncYear('arrival_date'))\ .values('year')\ .annotate(total=Count('id'))\ .order_by('year')
代码说明
- 先用
filter(或反向关联)筛选出目标游客的所有Arrival记录,避免全局查询带来的性能问题。 TruncYear('arrival_date')用于提取arrival_date字段的年份部分,作为分组依据。values('year')指定按年份分组。Count('id')统计每组内的记录数量,将结果存入total字段。order_by('year')确保结果按年份升序排列(可改为'-year'实现降序)。
内容的提问来源于stack exchange,提问作者Etsè FIATSI
相关产品推荐
相关产品推荐

