Django自定义icontainsall lookup:rhs仅接收%s问题求助
问题
想要创建一个自定义的icontainsall lookup,实现用户搜索带空格的短语时,将其转换为多个LIKE条件的AND查询(不限制单词顺序)。例如用户搜索'egg milk'时,生成的查询条件为name LIKE %egg% AND name LIKE %milk%。
现有lookup代码如下:
from django.db.models import CharField, Lookup, TextField class CaseInsensitiveContainsAllLookup(Lookup): lookup_name = 'icontainsall' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) print(lhs, rhs, lhs_params, rhs_params) # 输出为 "mytable"."name" %s [] ['egg milk'] predicate, params = [], [] # 转义\和% rhs_list = rhs.replace('\\', '\\\\').replace('%', '\\%').split(' ') for rhs in rhs_list: params += lhs_params + rhs_params predicate.append(f"LOWER({lhs}) LIKE LOWER({rhs})") return ' AND '.join(predicate), params CharField.register_lookup(CaseInsensitiveContainsAllLookup) TextField.register_lookup(CaseInsensitiveContainsAllLookup)
目前rhs仅接收%s而非实际的egg milk值,请问如何通过lookup实现预期需求?
解决方案
问题核心是你错误操作了占位符rhs,真实的搜索值存在rhs_params或self.rhs.value中。需要取出真实字符串拆分关键词,再逐个生成LIKE条件,同时处理通配符转义。
修改后的代码如下:
from django.db.models import CharField, Lookup, TextField class CaseInsensitiveContainsAllLookup(Lookup): lookup_name = 'icontainsall' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) # 取出真实的搜索字符串 search_value = self.rhs.value predicate, params = [], [] # 拆分关键词并过滤空字符串(避免连续空格生成无效条件) keywords = [kw.strip() for kw in search_value.split(' ') if kw.strip()] for keyword in keywords: # 转义SQL通配符:%、_、反斜杠 escaped_keyword = keyword.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_') # 拼接模糊匹配模板 like_pattern = f'%{escaped_keyword}%' # 添加条件和对应参数 predicate.append(f"LOWER({lhs}) LIKE LOWER(%s)") params.extend(lhs_params) params.append(like_pattern) return ' AND '.join(predicate), params CharField.register_lookup(CaseInsensitiveContainsAllLookup) TextField.register_lookup(CaseInsensitiveContainsAllLookup)
关键修改说明
- 获取真实值:直接通过
self.rhs.value拿到用户输入的原始搜索字符串,而非操作占位符%s - 清理关键词:拆分后过滤空字符串,避免连续空格生成
LIKE %%这类无效条件 - 通配符转义:对关键词中的
%、_、\进行转义,防止用户输入的特殊字符干扰SQL逻辑 - 生成独立条件:每个关键词对应一个
LIKE %keyword%,用AND连接,确保所有关键词都被匹配 - 参数绑定:正确收集每个条件的参数,保证参数顺序与SQL占位符一一对应
当用户搜索'egg milk'时,最终生成的SQL逻辑为:
WHERE LOWER("mytable"."name") LIKE LOWER(%s) AND LOWER("mytable"."name") LIKE LOWER(%s)
对应的参数是['%egg%', '%milk%'],完全符合预期的多关键词模糊匹配需求。
内容的提问来源于stack exchange,提问作者fishfin
相关产品推荐
相关产品推荐

