Django 4.x 视图中QuerySet条件order_by排序报错排查
问题根因
报错NameError: name 'Case' is not defined是因为缺少对应类的导入,你的条件排序实现思路完全正确,不需要调整核心逻辑。
修复方案
- 在
views.py文件顶部补充缺失的ORM表达式导入:
from django.db.models import Case, When, F, DateField
你代码中用到的Case、When、F、DateField都属于django.db.models模块,未导入时Python解释器无法识别对应名称,就会抛出NameError异常。
- 补全导入后原有代码即可正常运行,可根据业务需求做两点优化:
- 过滤条件可简化:将
filter(user__username=self.request.user)改为filter(user=self.request.user),直接用用户对象做关联查询,效率更高 - 排序规则可对齐原有模型默认配置:模型Meta默认先按
reading_progress排序,可在order_by中保留该规则,实现先按阅读进度分组、组内再按对应日期排序的效果,优化后的完整查询代码如下:
- 过滤条件可简化:将
reading_progress = ReadingProgress.objects.filter(user=self.request.user)\ .annotate( date_to_display=Case( When(reading_progress='1) On Reading List', then=F('date_added')), When(reading_progress='2) Reading In Progress', then=F('date_started')), When(reading_progress='3) Completed Reading', then=F('date_completed')), output_field=DateField(), # 若需要给默认进度'---'的记录指定排序字段,可加default参数,例: # default=F('date_created') ) ).order_by( 'reading_progress', # 先按阅读进度分组排序 '-date_to_display' # 组内按对应日期倒序(最新记录在前),正序则去掉字段前的'-' )
注意:如果
reading_progress为默认值'---'且未设置default参数,对应记录的date_to_display值为NULL,排序时会被放在结果集的最前/最后,可根据业务需要调整default值匹配需求。
内容的提问来源于stack exchange,提问作者Carewen
相关产品推荐
相关产品推荐

