如何为Redis+Flask实现的自动补全功能接入前端输入框实现动态触发
自动补全功能实现方案
1 修改Flask后端代码
调整根路由返回前端模板页面,其他原有接口逻辑保持不变,优化点添加了响应自动解码避免手动处理字节:
import redis import redisearch from flask import Flask,request,jsonify,render_template app = Flask("autocomplete") # 创建Redis连接,添加decode_responses自动将返回值转为字符串,无需手动解码 r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True) @app.route('/') def home(): # 返回前端模板页面 return render_template('index.html') # 向自动补全列表添加值的路由 @app.route('/add') def addValue(): try: name = request.args.get('name') n = name.strip() for l in range(1, len(n)): prefix = n[0:l] r.zadd('compl', {prefix: 0}) r.zadd('compl', {n+"*": 0}) return "Success" except: return "Failed" # 获取自动补全结果的路由 @app.route('/autocomplete') def autocomplete(): prefix = request.args.get('prefix') results = [] rangelen = 50 count = 5 start = r.zrank('compl', prefix) if not start: return jsonify(results) while len(results) != count: range_vals = r.zrange('compl', start, start + rangelen - 1) start += rangelen if not range_vals or len(range_vals) == 0: break for entry in range_vals: minlen = min(len(entry), len(prefix)) if entry[0:minlen] != prefix[0:minlen]: count = len(results) break if entry[-1] == "*" and len(results) != count: results.append(entry[0:-1]) return jsonify(results) if __name__ == '__main__': app.run(debug=True)
2 创建前端模板页面
在autocomplete.py同级目录新建名为templates的文件夹,在文件夹内新建index.html文件,代码如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>自动补全测试</title> <style> .autocomplete-container { width: 300px; margin: 100px auto; position: relative; } #search-input { width: 100%; padding: 8px 12px; font-size: 16px; box-sizing: border-box; } #autocomplete-results { position: absolute; width: 100%; list-style: none; margin: 0; padding: 0; border: 1px solid #eee; border-top: none; box-sizing: border-box; display: none; } #autocomplete-results li { padding: 8px 12px; cursor: pointer; background: #fff; } #autocomplete-results li:hover { background: #f5f5f5; } </style> </head> <body> <div class="autocomplete-container"> <input type="text" id="search-input" placeholder="输入内容搜索"> <ul id="autocomplete-results"></ul> </div> <script> const input = document.getElementById('search-input'); const resultsList = document.getElementById('autocomplete-results'); let timeout = null; // 监听输入事件,添加300ms防抖避免频繁请求接口 input.addEventListener('input', (e) => { const prefix = e.target.value.trim(); clearTimeout(timeout); if (!prefix) { resultsList.style.display = 'none'; resultsList.innerHTML = ''; return; } timeout = setTimeout(() => { fetch(`/autocomplete?prefix=${encodeURIComponent(prefix)}`) .then(res => res.json()) .then(results => { resultsList.innerHTML = ''; if (results.length === 0) { resultsList.style.display = 'none'; return; } results.forEach(item => { const li = document.createElement('li'); li.textContent = item; // 点击补全项自动填充到输入框 li.addEventListener('click', () => { input.value = item; resultsList.style.display = 'none'; }); resultsList.appendChild(li); }); resultsList.style.display = 'block'; }) }, 300); }); // 点击页面其他区域自动关闭补全列表 document.addEventListener('click', (e) => { if (!e.target.closest('.autocomplete-container')) { resultsList.style.display = 'none'; } }); </script> </body> </html>
3 功能测试步骤
- 启动本地Redis服务,确保6379端口可正常访问
- 先添加测试数据:启动Flask应用后,访问
http://localhost:5000/add?name=苹果、http://localhost:5000/add?name=苹果手机、http://localhost:5000/add?name=苹果电脑等测试词条 - 访问
http://localhost:5000,在输入框输入前缀即可看到对应的自动补全提示
可选优化方案
你找到的RediSearch Python客户端自带的自动补全实现,相比原生Zset实现不需要手动存储所有前缀字符串,存储空间占用更低,查询效率更高,适合数据量较大的生产场景使用。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

