Django 1.11 Admin自定义过滤器点击选项报错:无法解析关键字字段
解决Django 1.11 Admin自定义过滤器点击Yes/No报错的问题
这个问题我之前也碰到过,本质是自定义过滤器的逻辑写错了,导致Django误以为你要查询一个不存在的模型字段。咱们一步步来梳理解决:
错误原因分析
报错提示Cannot resolve keyword 'IsWithinRange' into field,说明你的自定义过滤器里,要么是parameter_name设置成了IsWithinRange(Django把它当成了模型字段名),要么是在queryset方法里错误地直接用IsWithinRange作为过滤条件——但你的模型里根本没有这个字段,自然会触发字段解析错误。
正确的自定义过滤器写法
假设你要实现的是基于现有字段(比如date_created或者predicted_result)的范围判断,下面是符合Django 1.11规范的代码示例:
from django.contrib import admin from django.utils import timezone class IsWithinRangeFilter(admin.SimpleListFilter): # 过滤器在Admin页面显示的标题 title = 'Is Within Range' # URL中使用的参数名,别用模型里没有的字段名,建议小写加下划线格式 parameter_name = 'within_range' def lookups(self, request, model_admin): # 返回过滤器的选项:(参数值, 页面显示文本) return ( ('yes', 'Yes'), ('no', 'No'), ) def queryset(self, request, queryset): # 根据选中的选项过滤查询集,必须用模型已有的字段做判断 selected_value = self.value() if not selected_value: return queryset # 这里替换成你的实际过滤逻辑,比如判断date_created是否在最近7天内 seven_days_ago = timezone.now() - timezone.timedelta(days=7) if selected_value == 'yes': return queryset.filter(date_created__gte=seven_days_ago) elif selected_value == 'no': return queryset.filter(date_created__lt=seven_days_ago) return queryset
关键注意事项
parameter_name不能乱设:别用模型里没有的字段名,也别用过滤器类名(比如IsWithinRange),否则Django会误以为要查询这个字段。queryset方法必须基于现有字段:所有过滤逻辑都要围绕模型已有的字段(比如date_created、predicted_result)来写,不能直接引用过滤器的名称或者自定义的非字段属性。- 正确注册过滤器:在你的Admin类里要正确添加这个过滤器,比如:
class YourModelAdmin(admin.ModelAdmin): list_display = ('id', 'user_question', 'predicted_result', 'date_created') list_filter = (IsWithinRangeFilter,) # 注册自定义过滤器
调试小技巧
如果还是报错,可以先打印self.value()看看URL传递的参数是什么,再检查queryset方法里的过滤条件是否正确引用了模型字段。
内容的提问来源于stack exchange,提问作者mmk
相关产品推荐
相关产品推荐

