Django多分组查询:按教师及外出类型统计当日有效外出记录
Django多分组统计:按教师+外出类型统计当日已确认外出记录
问题背景
已定义如下Tracker模型:
class Tracker(models.Model): grade = models.ForeignKey(Grade, on_delete=models.CASCADE) teacher = models.ForeignKey(User, on_delete=models.CASCADE) student = models.ForeignKey(Student, on_delete=models.CASCADE) BREAK_TYPE_CHOICES = [ ('1', 'Toilet Pass'), ('2', 'Hall Pass'), ('3', 'Doctor Pass'), ] break_type = models.CharField(max_length=10, choices=BREAK_TYPE_CHOICES) start_date_time = models.DateTimeField(auto_now_add=True) end_date_time = models.DateTimeField(auto_now=True) status = models.BooleanField(default=False)
需求是统计某一天内所有status=True的外出记录,先按教师分组,再按外出类型细分统计。目前已实现按教师单分组统计的代码:
breaks_today = Tracker.objects.filter(status=True, start_date_time__gte=date_from, end_date_time__lte=date_to) breaks_today = breaks_today.values('teacher').order_by('teacher').annotate(count=Count('teacher'))
需要进一步实现按教师+外出类型的多分组统计。
解决方案
只需在values()中同时指定teacher和break_type两个字段,并调整order_by的排序依据,即可实现多维度分组统计:
breaks_today = Tracker.objects.filter( status=True, start_date_time__gte=date_from, end_date_time__lte=date_to ).values('teacher', 'break_type') \ .order_by('teacher', 'break_type') \ .annotate(count=Count('id'))
代码说明
values('teacher', 'break_type'):指定按教师ID和外出类型码作为分组依据,Django会自动按这两个字段的组合进行分组。order_by('teacher', 'break_type'):确保结果先按教师排序,同一教师下再按外出类型排序,方便后续展示。annotate(count=Count('id')):用Count('id')统计每组的记录数(比Count('teacher')更准确,因为teacher是外键,可能存在重复关联,但id是唯一主键)。
扩展:获取可读性更高的统计结果
如果需要直接在查询结果中包含教师名称和外出类型的中文描述,可以调整values字段:
breaks_today = Tracker.objects.filter( status=True, start_date_time__gte=date_from, end_date_time__lte=date_to ).values( 'teacher__username', # 获取教师用户名 'break_type', 'break_type__display' # 直接获取外出类型的显示文本(Django 3.2+支持) ).order_by('teacher__username', 'break_type') \ .annotate(count=Count('id'))
如果使用的是低于3.2的Django版本,无法直接用break_type__display,可以在遍历结果时手动转换:
# 先定义类型映射字典 break_type_map = dict(Tracker.BREAK_TYPE_CHOICES) # 遍历统计结果添加显示文本 for item in breaks_today: item['break_type_name'] = break_type_map.get(item['break_type'], 'Unknown')
内容的提问来源于stack exchange,提问作者Irfan Harun
相关产品推荐
相关产品推荐

