Flask中接收搜索关键词应使用request.args.get('q', '')获取GET参数,需过滤空值并调用.strip()清洗空白符;SQLAlchemy中须用ilike(f'%{q}%')等参数化方式实现安全LIKE查询,禁用字符串拼接以防SQL注入。

Flask路由里怎么接收搜索关键词
用户输入的搜索词通常来自 GET 请求的查询参数,比如 /search?q=python。直接用 request.args.get('q', '') 获取最稳妥,别用 form 或 json——那是 POST 场景。
注意两点:空字符串要过滤掉,否则 LIKE '%%' 会全表扫描;还要做基础清洗,比如 .strip() 去首尾空格,避免搜 " flask " 匹配不到 "flask"。
- 永远检查
q是否为空或只含空白符,空则跳过查询或返回空列表 - 不建议在路由里直接拼 SQL 字符串,哪怕加了
%也要走参数化(见下一条) - 如果前端用了
encodeURIComponent,Flask 默认能正确解码,不用手动unquote
SQLAlchemy 中怎么安全写 LIKE 查询
核心是别用 Python 的 % 拼接字符串构造 WHERE name LIKE '%xxx%',这等于给 SQL 注入开后门。正确做法是把通配符和参数分开,让 SQLAlchemy 处理转义。
推荐用 ilike(PostgreSQL)或 like + collate(SQLite/MySQL),并用 % 包裹参数值:
立即学习“Python免费学习笔记(深入)”;
db.session.query(User).filter(User.name.ilike(f'%{q}%'))如果用原生 SQL(比如 text),必须用命名参数:
db.session.execute(text("SELECT * FROM user WHERE name LIKE :pattern"), {"pattern": f"%{q}%"})-
ilike自动忽略大小写,比lower(name) LIKE lower(:q)效率高 - SQLite 默认不支持
ilike,得显式加collate nocase:User.name.like(f'%{q}%', escape='\') - 用户输入里若含
%、_或转义符,要用escape参数防误匹配,例如like('...%...', escape='\')并提前把q中的替换为\
为什么搜索结果分页不能用 OFFSET LIMIT 做深分页
当用户翻到第 100 页(OFFSET 2000),数据库仍要扫描前 2000 行再丢弃,响应明显变慢。尤其模糊查询本身可能就慢,叠加深分页更卡。
简单项目可先用 paginate,但要注意它底层仍是 OFFSET:
users = User.query.filter(User.name.ilike(f'%{q}%')).paginate(page=page, per_page=10)- 小数据量(paginate 足够用
- 一旦发现第 50 页开始延迟 >500ms,就得切到游标分页(基于上一页最后 ID 或时间戳)
- 别在模糊搜索结果上盲目加
ORDER BY id DESC再分页——排序本身就会拖慢 LIKE 查询,除非字段有索引
搜索字段没索引会导致全表扫描
哪怕只查 1000 行,LIKE '%python%' 也会让数据库放弃索引走全表。只有 LIKE 'python%'(前缀匹配)才能用上 B-tree 索引。
如果业务真需要中间匹配,考虑这些替代方案:
- 给字段加
GIN索引(PostgreSQL)配合to_tsvector做全文检索,比 LIKE 快一个数量级 - SQLite 可启用
FULLTEXT表,用MATCH替代LIKE - MySQL 用
fulltext索引 +MATCH ... AGAINST,注意中文需 ngram 分词插件 - 纯 Python 做内存过滤(仅限极小数据集),用
[u for u in users if q.lower() in u.name.lower()],但别在生产环境对几千行以上这么干
模糊搜索看着简单,实际卡点全在数据库层——关键词怎么进、通配符怎么处理、分页怎么扛、索引怎么建,漏掉任一环,用户搜个“a”都要等两秒。


















