Django DRF自定义过滤器报filter_name__icontains未定义解决方案
报错原因
你触发NameError的根本原因是字典键的写法不符合Python语法规则:当你写{filter_name__icontains: term.get(filter_name)}时,Python解释器会将filter_name__icontains识别为一个独立的变量名尝试取值,不会自动将filter_name变量的内容和__icontains后缀做拼接,由于代码里从来没有定义过叫这个名字的变量,自然会抛出未定义的报错。
修复方案
Django ORM的字段查找表达式本质是字符串格式的键,你只需要通过字符串拼接/f-string的方式,提前把字段名和查找后缀拼成完整的字符串键,再传给filter方法即可。
另外原代码中直接对比__class__判断字段类型的写法存在兼容问题,换成isinstance判断可以覆盖所有CharField的子类字段(比如EmailField、URLField、SlugField等),同时可以补充空值跳过逻辑,避免传入空过滤值时生成无效查询。
修正后的完整代码如下:
from django.db.models import QuerySet, CharField from rest_framework.filters import BaseFilterBackend from rest_framework.request import Request class AbstractFilterBackend(BaseFilterBackend): @staticmethod def __execute_default_filters(queryset, terms: list): for term in terms: filter_name = next(iter(term.keys())) filter_value = term.get(filter_name) # 跳过空过滤值,避免无效查询 if not filter_value: continue if hasattr(queryset.model, filter_name): model_field = queryset.model._meta.get_field(filter_name) # CharField类型字段使用icontains模糊匹配 if isinstance(model_field, CharField): lookup_key = f"{filter_name}__icontains" else: lookup_key = filter_name queryset = queryset.filter(**{lookup_key: filter_value}) return queryset
关键改动说明
- 用f-string生成
字段名__icontains格式的字符串作为查询键,解决变量识别错误的问题 - 字段类型判断改用
isinstance,兼容CharField子类字段 - 新增空值判断逻辑,过滤空参数场景
内容的提问来源于stack exchange,提问作者mascai
相关产品推荐
相关产品推荐

