Django应用报'NoneType'对象无'day'属性 仅部分填充course_schedule时触发
Django 报错
'NoneType' object has no attribute 'day' 排查与修复 报错现象
- 触发路径:访问
/en/sir_course接口,由sir_course视图的 POST 逻辑触发 - 触发规律:仅当
course_schedule模型未为所有课程配置对应排期(比如一周7天仅填充3天的排期数据,存在数据缺漏)时触发报错;为所有课程补全对应关联的排期数据后,报错消失、功能正常 - 完整报错日志:
Traceback (most recent call last): File "C:\\Users\\Habib\\Documents\\django\\FIVERR\\Ayyub_SMS\\venv\\lib\\site-packages\\django\\core\\handlers\\exception.py", line 47, in inner response = get_response(request) File "C:\\Users\\Habib\\Documents\\django\\FIVERR\\Ayyub_SMS\\venv\\lib\\site-packages\\django\\core\\handlers\\base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\\Users\\Habib\\Documents\\django\\FIVERR\\Ayyub_SMS\\sms\\schoolapp\\views.py", line 1754, in sir_course get_all = getall(2021, sch.day) Exception Type: AttributeError at /en/sir_course Exception Value: 'NoneType' object has no attribute 'day'
核心根因
视图中获取课程排期的逻辑没有做数据缺失的容错:
- 现有代码通过
sch = course_schedule.objects.get(id=course.Course_Name.pk)按课程主键直接匹配排期记录,course_schedule和add_courses模型之间没有显式外键关联,全靠代码手动匹配主键 - 当某个被老师绑定的课程没有对应的排期记录时,
course_schedule.objects.get()会抛出DoesNotExist异常,未被捕获的情况下最终返回空值,后续访问sch.day属性时就会触发NoneType无对应属性的报错 - 之前观察到的“全量填充不报错”本质是数据完全匹配时没有出现空值的情况,只要存在1条无排期的课程记录,整个流程就会中断。
修复步骤
1. 给排期查询加异常捕获
替换原视图中无容错的查询逻辑,遇到无排期的课程直接跳过,不中断整体排期表生成流程:
原问题代码:
for course in get_course_name_th: sch = course_schedule.objects.get(id=course.Course_Name.pk) get_all = getall(2021, sch.day)
修改后代码:
for course in get_course_name_th: # 捕获无排期的异常,跳过对应课程 try: sch = course_schedule.objects.get(id=course.Course_Name.pk) except course_schedule.DoesNotExist: continue get_all = getall(2021, sch.day)
2. (可选优化)补全模型关联关系
手动靠主键匹配的关联逻辑长期维护容易出问题,可给 course_schedule 增加指向 add_courses 的外键,从模型层面固化关联关系,同时修正原代码里的拼写错误(Wednessday 改为 Wednesday):
class course_schedule(models.Model): # 新增和课程的显式外键关联 related_course = models.ForeignKey(add_courses, on_delete=models.CASCADE, related_name="course_schedule") days_choices = ( ("Mon", 'Monday'), ("Tue", 'Tuesday'), ('Wed', "Wednesday"), ('Thurs', "Thursday"), ('Fri', "Friday"), ('Sat', "Saturday"), ("Sun", "Sunday"), ) day = models.CharField(max_length=60, default="Sun") time_session = models.CharField(max_length=150, default='8:00am') end_session = models.CharField(max_length=150, default='10:00am')
3. (小优化)简化排期字典拼接逻辑
原代码通过 try/except KeyError 判断字典键是否存在的写法可直接替换为字典内置的 setdefault 方法,减少冗余代码:
原逻辑:
try: if days[str(date)]: days[str(date)].append(str(course.Course_Name.Course_Name)+" "+str(course.Course_Name.course_code)) except KeyError: days[str(date)] = [str(course.Course_Name.Course_Name)+" "+str(course.Course_Name.course_code),]
优化后逻辑:
date_str = n.strftime("%d/%m/%Y") course_info = f"{course.Course_Name.Course_Name} {course.Course_Name.course_code}" days.setdefault(date_str, []).append(course_info)
内容的提问来源于stack exchange,提问作者coderboy
相关产品推荐
相关产品推荐

