Django-filter中MultipleChoiceFilter设置iexact仍大小写敏感报错
问题根因
MultipleChoiceFilter配置的lookup_expr='iexact'仅在数据库查询阶段生效,不会覆盖参数合法性校验的默认逻辑:过滤器会在执行查询前,先将传入的参数值与choices中定义的选项值做大小写敏感的精确匹配,你传入的小写eng/deu和选项里定义的大写ENG/DEU无法匹配,因此直接抛出Select a valid choice校验错误,根本不会走到后续的数据库查询步骤,iexact配置自然不会产生效果。
修复方案
自定义继承MultipleChoiceFilter的子类,重写入参转换方法,在选项校验前统一将传入值做大小写归一化,对齐choices的格式即可:
class CaseInsensitiveMultipleChoiceFilter(filters.MultipleChoiceFilter): def to_python(self, value): # 入参统一转为大写,匹配choices定义的选项格式 return value.upper() if isinstance(value, str) else value class PostFilter(filters.FilterSet): lang = CaseInsensitiveMultipleChoiceFilter( field_name='language', choices=[('ENG', 'ENG'), ('DEU', 'DEU')], lookup_expr='iexact' ) class Meta: fields = ('lang',) model = Post
修改后再发起posts/?lang=eng&lang=deu请求时,入参会先被转为大写通过选项校验,后续查询阶段iexact规则会正常生效,兼容数据库中language字段大小写不同的存储值。
提示:如果你的
language字段在PostgreSQL中本身就固定存储大写值,也可以去掉lookup_expr='iexact'配置,直接用默认的exact匹配即可,查询性能更优。
内容的提问来源于stack exchange,提问作者Alexey Dudarev
相关产品推荐
相关产品推荐

