You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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块但未找到原因,请问如何修改让循环遍历所有日期?

修复方案

核心问题分析

  1. 循环提前终止:原代码在循环内部直接return result,导致第一次迭代就结束函数,后续日期完全没有处理。
  2. 结果未合并:每次循环都重新执行查询,没有将多个日期的筛选结果合并。
  3. 缺乏异常处理:未处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:56:10