如何在Django ORM中检查用户状态并按规则创建Timesheet
问题分析与解决方案
需求回顾
需在满足以下任意条件时为用户创建Timesheet,若用户存在Pending状态的休假记录,则禁止创建:
- 存在状态为
Cancelled和Approved的休假记录 - 存在状态为
Rejected和Cancelled的休假记录 - 存在至少2条
Cancelled状态的休假记录
现有代码的问题
- 未实现需求中的核心条件判断:当前代码仅查询了休假记录的存在性,但未验证三个创建条件,也未检查是否存在
Pending状态 - 未将条件判断与Timesheet创建逻辑关联:无论是否满足条件,都会直接创建/更新Timesheet
- 存在冗余代码:比如
User.objects.get(id=att.employee_id)可直接用att.employee替代,重复字段赋值可简化
修正后的代码实现
import calendar from datetime import datetime from django.db.models import Q def submit_attendance(request, approval_status=None): if request.method == "POST": month = request.POST.get("month") year = request.POST.get("year") # 计算指定月份的起止日期 year_int = int(year) month_int = int(month) first, last = calendar.monthrange(year_int, month_int) month_first_date = datetime.date(year_int, month_int, 1) month_last_day = datetime.date(year_int, month_int, last) # 获取当前用户指定月份内的考勤记录 attendance_objects = Attendance.objects.filter( employee=request.user, date__month=month_int, date__year=year_int ) # 获取当前用户指定月份内的所有休假记录状态 leave_statuses = EmployeeLeaves.objects.filter( employee=request.user, from_date__gte=month_first_date, to_date__lte=month_last_day ).values_list('approval_status', flat=True) # 统计各休假状态的数量 status_count = {} for status in leave_statuses: status_count[status] = status_count.get(status, 0) + 1 # 判断是否满足Timesheet创建条件 can_create = False if 'Pending' not in status_count: # 检查三个创建条件是否满足任意一个 has_canceled = status_count.get('Cancelled', 0) >= 1 condition1 = has_canceled and ('Approved' in status_count) condition2 = has_canceled and ('Rejected' in status_count) condition3 = status_count.get('Cancelled', 0) >= 2 can_create = condition1 or condition2 or condition3 # 仅当满足条件时,处理Timesheet的创建/更新 if can_create: for att in attendance_objects: # 使用get_or_create简化创建/更新逻辑 time_sheet_obj, created = Timesheet.objects.get_or_create( employee=request.user, date=att.date, status=1, defaults={ 'workingday_holiday': att.workingday_holiday, 'in_time': att.in_time, 'out_time': att.out_time, 'shift': att.shift, 'working_hours': att.working_hours, 'remarks': att.remarks } ) # 如果是已存在的记录,更新字段 if not created: time_sheet_obj.workingday_holiday = att.workingday_holiday time_sheet_obj.in_time = att.in_time time_sheet_obj.out_time = att.out_time time_sheet_obj.shift = att.shift time_sheet_obj.working_hours = att.working_hours time_sheet_obj.remarks = att.remarks time_sheet_obj.save() # 更新考勤记录状态 att.status = 0 if created else 1 att.save()
关键优化点
- 核心条件判断:先统计休假状态的分布,严格按照需求验证创建条件,同时排除
Pending状态的情况 - 简化创建逻辑:使用
get_or_create替代try-except块,减少冗余代码,同时明确区分创建和更新场景 - 性能优化:批量获取休假状态而非多次查询,减少数据库交互次数
- 逻辑关联:仅当满足条件时才执行Timesheet的创建/更新操作,符合需求规则
内容的提问来源于stack exchange,提问作者Siva
相关产品推荐
相关产品推荐

