Django查询报错Cannot resolve keyword '-name',求原因及替代方案
Django查询报错:Cannot resolve keyword '-name' into field 问题解决
问题描述
执行以下Django查询时遇到错误:Cannot resolve keyword '-name' into field. Choices are: name, account, account_id
self.queryset = Model.objects.order_by( Case( When(status='pending', then=0), When(status='rejected', then=1), When(status='accepted', then=2), default=3 ), Case( When(status='pending', then='-name'), default='-account' ) )
错误原因
Django的Case/When语句中,then参数只能返回字段值或常量,不能直接传入带负号的字符串(比如'-name')作为排序指令。Django会把'-name'当作一个字段名去数据库中匹配,而你的模型里并没有名为'-name'的字段,因此触发该错误。
实现预期结果的方法
你的需求是:先按status的自定义顺序(pending→rejected→accepted→其他)排序,再根据status的值选择后续排序字段(pending时按name倒序,其他情况按account倒序),可以用以下两种方式实现:
方法1:使用Desc表达式(Django 2.0+ 支持)
直接在then中传入Desc('字段名')来指定倒序排序,Case会返回正确的排序表达式而非字符串:
from django.db.models import Case, When, Desc self.queryset = Model.objects.order_by( Case( When(status='pending', then=0), When(status='rejected', then=1), When(status='accepted', then=2), default=3 ), Case( When(status='pending', then=Desc('name')), default=Desc('account') ) )
方法2:动态生成排序参数(兼容低版本Django)
如果你的Django版本低于2.0,可以通过动态拼接order_by的参数来实现:
from django.db.models import Case, When, F # 先定义status的自定义排序规则 status_order = Case( When(status='pending', then=0), When(status='rejected', then=1), When(status='accepted', then=2), default=3 ) # 分情况处理二级排序 self.queryset = Model.objects.annotate( sort_key=status_order ).order_by( 'sort_key', # 先按字段值排序,再整体倒序,通过Case控制使用哪个字段 Case( When(status='pending', then=F('name')), default=F('account') ).desc() )
内容的提问来源于stack exchange,提问作者Digvijay Nikam
相关产品推荐
相关产品推荐

