Django多对多关联下多日期筛选导师查询循环终止问题解决
问题描述
我有一个用于多对多关系的导师可用性表,导师需录入多个授课日期,示例如下:
Availability Tutor: user available_day time t1 Sun 6,7,8 t2 mon 3,4 t1 mon 1,2
我希望根据搜索日期筛选所有符合条件的导师。
模型定义:
class TutorProfile(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE) tutor_availablility = models.ManyToManyField( Day)
查询集代码:
def get_queryset(self): subject_param = self.request.GET.get('subject') bookday = self.request.GET.get('book_day') grade = self.request.GET.get('grade') li = list(bookday.split(",")) print("Book Info:", li) for i in range(len(li)): print(li[i]) _day_name = datetime.strptime(li[i], "%d-%m-%Y").strftime("%A") print("Day Name:", _day_name) day_num = Day.objects.get(day_name=_day_name) print("Day_Num",day_num) result = TutorProfile.objects.filter( tutor_availablility=day_num).all() return result
运行该查询时,循环仅执行一次就停止,无法遍历多个日期且出现异常。尝试添加try-catch块但未找到原因,请问如何修改让循环遍历所有日期?
修复方案
核心问题分析
- 循环提前终止:原代码在循环内部直接
return result,导致第一次迭代就结束函数,后续日期完全没有处理。 - 结果未合并:每次循环都重新执行查询,没有将多个日期的筛选结果合并。
- 缺乏异常处理:未处理
datetime.strptime格式错误、Day.DoesNotExist等异常情况,容易触发崩溃。
修改后的代码
根据需求分两种场景实现:
场景1:筛选所有指定日期都有空的导师
如果需要导师在每一个搜索日期都有可用时间,使用连续的filter叠加条件:
from django.db.models import Q import datetime from django.core.exceptions import ObjectDoesNotExist def get_queryset(self): subject_param = self.request.GET.get('subject') bookday = self.request.GET.get('book_day') grade = self.request.GET.get('grade') queryset = TutorProfile.objects.all() # 处理学科和年级筛选(如果模型对应字段存在) if subject_param: queryset = queryset.filter(subject=subject_param) if grade: queryset = queryset.filter(grade=grade) if bookday: li = bookday.split(",") day_ids = [] for date_str in li: try: # 转换日期为星期名称,去除字符串首尾空格避免格式错误 _day_name = datetime.strptime(date_str.strip(), "%d-%m-%Y").strftime("%A") # 不区分大小写匹配星期名称,兼容输入差异 day = Day.objects.get(day_name__iexact=_day_name) day_ids.append(day.id) except (ValueError, ObjectDoesNotExist): # 跳过格式错误或不存在的日期,不中断程序 continue # 叠加筛选条件:导师必须包含所有指定日期 for day_id in day_ids: queryset = queryset.filter(tutor_availablility=day_id) return queryset
场景2:筛选任意一个指定日期有空的导师
如果只要导师在任意一个搜索日期有可用时间,使用Q对象实现OR条件:
from django.db.models import Q import datetime from django.core.exceptions import ObjectDoesNotExist def get_queryset(self): subject_param = self.request.GET.get('subject') bookday = self.request.GET.get('book_day') grade = self.request.GET.get('grade') queryset = TutorProfile.objects.all() # 处理学科和年级筛选(如果模型对应字段存在) if subject_param: queryset = queryset.filter(subject=subject_param) if grade: queryset = queryset.filter(grade=grade) if bookday: li = bookday.split(",") q_objects = Q() for date_str in li: try: _day_name = datetime.strptime(date_str.strip(), "%d-%m-%Y").strftime("%A") day = Day.objects.get(day_name__iexact=_day_name) # 累加OR条件 q_objects |= Q(tutor_availablility=day) except (ValueError, ObjectDoesNotExist): continue # 应用OR条件筛选 if q_objects: queryset = queryset.filter(q_objects) return queryset
关键改进点
- 移除循环内的
return语句,先收集所有有效日期,再统一执行筛选逻辑。 - 添加异常处理,跳过无效日期,避免程序因输入错误崩溃。
- 使用
__iexact匹配星期名称,兼容大小写输入差异(如Sun和sun)。 - 支持两种常见筛选逻辑,可根据实际业务需求选择。
内容的提问来源于stack exchange,提问作者Iqbal Hussain
相关产品推荐
相关产品推荐

