在Django中按月份统计员工考勤总时长的需求
按月份统计考勤总时长的解决方案
高效实现:利用Django ORM聚合分组
推荐直接通过数据库层面的分组聚合完成统计,相比Python循环遍历效率更高,尤其适合数据量较大的场景。
假设你的Attendance模型包含attendance_date(考勤日期)和total_time(单条记录时长)字段,修改视图代码如下:
from django.db.models import Sum, Coalesce from django.db.models.functions import ExtractYear, ExtractMonth def emp_attendance(request): # 按年份、月份分组,统计每个月的总时长 attendance_by_month = Attendance.objects.filter( total_time__isnull=False # 过滤掉时长为空的无效记录 ).values( year=ExtractYear('attendance_date'), month=ExtractMonth('attendance_date') ).annotate( # 用Coalesce将空值转为0,避免求和结果为None total_duration=Sum(Coalesce('total_time', 0)) ).order_by('year', 'month') # 按年月排序,保证统计顺序 # 保留全量考勤列表(如果模板需要展示单条记录) attendance_list_ad = Attendance.objects.all() return render(request, 'employee/emp_attendance.html', { 'attendance_list_ad': attendance_list_ad, 'attendance_by_month': attendance_by_month })
模板展示示例
在emp_attendance.html中可这样遍历展示月度统计结果:
<h3>月度考勤总时长统计</h3> <ul> {% for entry in attendance_by_month %} <li>{{ entry.year }}年{{ entry.month }}月:{{ entry.total_duration }}</li> {% endfor %} </ul>
备选方案:Python循环实现分组统计
如果需要保留原有循环逻辑,可通过字典存储各月份的累计时长:
def emp_attendance(request): attendance_list_ad = Attendance.objects.all() total_by_month = {} for item in attendance_list_ad: if item.total_time is not None and item.attendance_date: # 用(年,月)作为字典键,确保分组唯一 year_month_key = (item.attendance_date.year, item.attendance_date.month) if year_month_key in total_by_month: total_by_month[year_month_key] += item.total_time else: total_by_month[year_month_key] = item.total_time # 将字典转为易读的列表格式,方便模板遍历 formatted_monthly_totals = [ {'year': k[0], 'month': k[1], 'total': v} for k, v in sorted(total_by_month.items()) ] return render(request, 'employee/emp_attendance.html', { 'attendance_list_ad': attendance_list_ad, 'formatted_monthly_totals': formatted_monthly_totals })
内容的提问来源于stack exchange,提问作者Nishant Sharma
相关产品推荐
相关产品推荐

