如何为Flask健康主题搜索引擎实现结果分页功能?
Flask健康维基搜索引擎分页实现方案
我用Flask开发了一个检索健康主题维基百科语料的搜索引擎,部分查询会返回数百条结果,需要添加分页功能(每页展示10-20条)。当前页面底部已有分页按钮但无实际功能,我尝试引入flask_paginate配置后端分页逻辑,但不清楚如何修改index.html实现前端分页展示。以下是我的相关代码:
原index.html代码
{% extends "base.html" %} {% block title %}Search Page{% endblock %} {% block contents %} <div class="container"> <div class="row"> <div class="col-lg-12"> <div class="search-result-box card-box"> <div class="row"> <div class="col-md-8 offset-md-2"> <div class="pt-3 pb-4"> <div class="search-form"> <form action="#" method="POST"> <div class="input-group"> <input type="text" name="msg" class="form-control input-lg"> <div class="input-group-btn"> <button class="btn btn-primary" type="submit">Search</button> </div> </div> </form> </div> <div class="mt-4 text-center"><h4>Search Results For {{user_query}}</h4></div> </div> </div> </div> <!-- end row --> <ul class="nav nav-tabs tabs-bordered"> <li class="nav-item"><a href="#home" data-toggle="tab" aria-expanded="true" class="nav-link active">All results <span class="badge badge-success ml-1">{{search_results_list|length}}</span></a></li> </ul> <div class="tab-content"> <div class="tab-pane active" id="home"> <div class="row"> <div class="col-md-12"> <div class="search-item"> {% if search_results_list|length > 0 %} {% for r in search_results_list %} <div class="font-13 text-success mb-3"><a href='{{r[0]}}' target="_blank">{{r[0]}}</a></div> <div class="font-13 text-success mb-3"><p target="_blank">{{r[1]}}</p></div> {% endfor %} {% else %} <p class="mt-4 text-center">No search result</P> {% endif %} </div> <ul class="pagination justify-content-end pagination-split mt-0"> <li class="page-item"><a class="page-link" href="#" aria-label="Previous"><span aria-hidden="true">«</span> <span class="sr-only">Previous</span></a></li> <li class="page-item active"><a class="page-link" href="#">1</a></li> <li class="page-item"><a class="page-link" href="#" aria-label="Next"><span aria-hidden="true">»</span> <span class="sr-only">Next</span></a></li> </ul> <div class="clearfix"></div> </div> </div> </div> <!-- end All results tab --> </div> </div> </div> </div> <!-- end row --> </div> <!-- Footer --> <footer id="main-footer" class="pt-2 py-4 bg-dark text-white text-center"> Copyright © <span class="year"></span> Team Dream </footer> <!-- container --> {% endblock %}
原Flask后端代码
from flask import Flask, render_template, request from search_engine import query_prep, OkapiBM25 import pickle app = Flask(__name__) @app.route('/') def results(): return render_template('index.html') @app.route('/', methods=['POST']) def process_res(): with open("inv_index.pickle", "rb") as file: inv_ind = pickle.load(file) user_search_query = request.form['msg'] queries = {'q': query_prep(user_search_query)} ranking = OkapiBM25(inv_ind, queries)['q'] seen = set() newRes= [] myDict = pickle.load(open('text_summaries.pickle','rb')) for r in ranking: newRes.append((r[1], myDict[r[1]])) return render_template('index.html', search_results_list = newRes, user_query=user_search_query) if __name__ == "__main__": app.run(debug=True)
修改后的分页相关后端代码
from flask_paginate import Pagination, get_page_parameter def process_res(): with open("inv_index.pickle", "rb") as file: inv_ind = pickle.load(file) user_search_query = request.form['msg'] queries = {'q': query_prep(user_search_query)} ranking = OkapiBM25(inv_ind, queries)['q'] seen = set() newRes= [] myDict = pickle.load(open('text_summaries.pickle','rb')) for r in ranking: newRes.append((r[1], myDict[r[1]])) page = request.args.get(get_page_parameter(), type=int, default=1) pagination = Pagination(page=page, total=len(newRes), search=user_search_query, record_name='Search Results') return render_template('index.html', search_results_list = newRes, user_query=user_search_query, Pagination = pagination)
解决方案
1. 修正后端分页逻辑
当前后端仅初始化了Pagination对象,但未对结果列表做分页截取,也未指定每页展示数量。修改后的完整后端代码如下:
from flask import Flask, render_template, request, session from search_engine import query_prep, OkapiBM25 import pickle from flask_paginate import Pagination, get_page_parameter app = Flask(__name__) app.secret_key = 'your_custom_secret_key_here' # 必须设置session密钥 @app.route('/') def results(): return render_template('index.html') @app.route('/', methods=['POST', 'GET']) def process_res(): # 处理搜索请求 if request.method == 'POST': user_search_query = request.form['msg'] # 保存搜索关键词和结果到session,分页时复用 session['search_query'] = user_search_query with open("inv_index.pickle", "rb") as file: inv_ind = pickle.load(file) queries = {'q': query_prep(user_search_query)} ranking = OkapiBM25(inv_ind, queries)['q'] newRes= [] myDict = pickle.load(open('text_summaries.pickle','rb')) for r in ranking: newRes.append((r[1], myDict[r[1]])) session['all_results'] = newRes else: # 分页请求时从session获取历史数据 user_search_query = session.get('search_query', '') newRes = session.get('all_results', []) # 分页核心配置 page = request.args.get(get_page_parameter(), type=int, default=1) per_page = 10 # 每页展示10条,可调整为20 start = (page - 1) * per_page end = start + per_page paginated_results = newRes[start:end] pagination = Pagination( page=page, total=len(newRes), per_page=per_page, record_name='搜索结果', css_framework='bootstrap4' # 匹配你的Bootstrap版本 ) return render_template( 'index.html', search_results_list=paginated_results, user_query=user_search_query, pagination=pagination ) if __name__ == "__main__": app.run(debug=True)
关键修改说明:
- 路由新增
GET方法支持,分页请求为GET类型 - 使用
session存储搜索关键词和全部结果,避免分页时重复执行搜索逻辑 - 添加
per_page参数控制每页条数,对结果列表做切片得到当前页数据 - 指定
css_framework适配前端Bootstrap样式,自动生成符合UI的分页组件
2. 修改前端index.html模板
替换静态分页按钮为flask_paginate生成的动态组件,同时优化结果展示逻辑:
{% extends "base.html" %} {% block title %}Search Page{% endblock %} {% block contents %} <div class="container"> <div class="row"> <div class="col-lg-12"> <div class="search-result-box card-box"> <div class="row"> <div class="col-md-8 offset-md-2"> <div class="pt-3 pb-4"> <div class="search-form"> <form action="#" method="POST"> <div class="input-group"> <input type="text" name="msg" class="form-control input-lg" value="{{ user_query or '' }}"> <div class="input-group-btn"> <button class="btn btn-primary" type="submit">Search</button> </div> </div> </form> </div> {% if user_query %} <div class="mt-4 text-center"><h4>Search Results For {{user_query}}</h4></div> {% endif %} </div> </div> </div> <!-- end row --> {% if search_results_list %} <ul class="nav nav-tabs tabs-bordered"> <li class="nav-item"><a href="#home" data-toggle="tab" aria-expanded="true" class="nav-link active">All results <span class="badge badge-success ml-1">{{ search_results_list|length }}</span></a></li> </ul> <div class="tab-content"> <div class="tab-pane active" id="home"> <div class="row"> <div class="col-md-12"> <div class="search-item"> {% for r in search_results_list %} <div class="font-13 text-success mb-3"><a href='{{r[0]}}' target="_blank">{{r[0]}}</a></div> <div class="font-13 text-muted mb-3"><p>{{r[1]}}</p></div> {% endfor %} </div> <!-- 替换静态分页为动态组件 --> <div class="d-flex justify-content-end mt-4"> {{ pagination.links }} </div> <div class="clearfix"></div> </div> </div> </div> <!-- end All results tab --> </div> {% else %} {% if user_query %} <p class="mt-4 text-center">No search result</p> {% endif %} {% endif %} </div> </div> </div> <!-- end row --> </div> <!-- Footer --> <footer id="main-footer" class="pt-2 py-4 bg-dark text-white text-center"> Copyright © <span class="year"></span> Team Dream </footer> <!-- container --> {% endblock %}
关键修改说明:
- 搜索框默认填充历史查询关键词,提升用户体验
- 移除静态分页按钮,使用
{{ pagination.links }}自动生成带跳转功能的分页组件 - 优化空结果判断逻辑,避免初始页面显示"No search result"
- 微调摘要文本样式,避免和链接颜色重复
内容的提问来源于stack exchange,提问作者hulio_entredas
相关产品推荐
相关产品推荐

