一、前言
現在開發一個網站,分頁是一個很常見的功能了,尤其是當數據達到一定量的時候,如果都顯示在頁面上,會造成頁面過長而影響用戶體驗,除此之外,還可能出現加載過慢等問題。因此,分頁就很有必要了。
分頁功能的常用的實現方法有兩種:前台分頁和后台分頁。前台分頁就是一次查詢取出所有數據保存在內存中,需要的時候就從相應區間中取數據,但只適用於少量數據的情況。后台分頁就是查詢時只取出相應區間中的數據並返回,翻頁時再次查詢並取數據,此方法能減小傳輸壓力提高性能。今天這篇博客就記錄一下在 Flask 中怎么使用 Flask 的擴展庫 flask-pagination 和分頁插件 layPage 實現分頁功能。
二、准備工作
1.Flask 環境配置
首先你需要一個 Python 環境,然后需要安裝幾個第三方庫:
- flask
- pymysql
- flask-pagination
- SQLAlchemy
使用如下命令進行安裝:
pip install flask
pip install pymysql
pip install flask-pagination
pip install SQLAlchemy
2.layui 下載安裝
layui 是一個經典模塊化前端 UI 框架,網址為:https://www.layui.com/,也可以直接點擊這里進行下載。
layui 是一款采用自身模塊規范編寫的前端 UI 框架,遵循原生 HTML/CSS/JS 的書寫與組織形式,門檻極低,拿來即用。其外在極簡,卻又不失飽滿的內在,體積輕盈,組件豐盈,從核心代碼到 API 的每一處細節都經過精心雕琢,非常適合界面的快速開發。
3.數據准備
這次使用的數據庫是 MySQL,建了一個表 students,這個表只有兩個字段:stu_id 和 stu_name,表中數據如下:
三、使用flask-pagination
要使用 flask-pagination 來進行分頁,需要從中導出一個類 Pagination:
from flask_paginate import Pagination
下面是分頁的代碼:
1 @app.route('/index') 2 def index(limit=10): 3 sess = DBSession() 4 data = sess.query(t_students).all() 5 page = int(request.args.get("page", 1)) 6 start = (page - 1) * limit 7 end = page * limit if len(data) > page * limit else len(data) 8 paginate = Pagination(page=page, total=len(data)) 9 ret = sess.query(t_students).slice(start, end) 10 return render_template("index.html", data=ret, paginate=paginate)
其中 limit 表示每頁顯示的條數,page 代表頁數,start 和 end 分別表示該頁面顯示的數據區間,然后實例化 Pagination 類。這里我只傳入了兩個參數:page 和 total(total 代表數據總條數),除了這兩個參數,還可以傳入其他參數,例如:
- bs_version:支持的 BootStrap 版本,默認為2;
- css_framework:使用的 CSS 框架,默認為 BootStrap;
- url_coding:URL 編碼格式,默認為 UTF-8。
在代碼中,我使用了 render_template 來渲染頁面並返回數據,下面是前端中的核心代碼:
1 <table> 2 <thead> 3 <tr> 4 <th>ID</th> 5 <th>NAME</th> 6 </tr> 7 </thead> 8 <tbody> 9 {% for i in data %} 10 <tr> 11 <td>{{ i.stu_id }}</td> 12 <td>{{ i.stu_name }}</td> 13 </tr> 14 {% endfor %} 15 </tbody> 16 </table> 17 {{ paginate.links }}
最終得到的結果如下:
四、使用layPage
可以看到使用 flask-pagination 得到的分頁效果是比較簡單的,但如果想要更好的效果,可以使用一些前端框架來實現,例如 layui 中的分頁插件 layPage。layPage 致力於提供極致的分頁邏輯,既可輕松勝任異步分頁,也可作為頁面刷新式分頁,可以在這里查看文檔。
首先需要導入 layui.js 和 layui.css:
<script src="../static/layui.js"></script>
<link rel="stylesheet" href="../static/css/layui.css">
laypage 的使用非常簡單,指向一個用於存放分頁的容器,通過服務端得到一些初始值,即可完成分頁渲染。例如:

1 <div> 2 <table> 3 <thead> 4 <tr> 5 <th></th> 6 <th>ID</th> 7 <th>NAME</th> 8 </tr> 9 </thead> 10 <tbody id="demoBody"></tbody> 11 </table> 12 <div id="demo"></div> 13 </div>
其中 demo 用於存放分頁,demoBody 則用於顯示數據內容。但要實現分頁,還需要使用 laypage.render() 來渲染。在 laypage.render() 中,有一些核心參數:
- elem:指向存放分頁的容器,可以是 ID、DOM 對象;
- count:數據總量,一般通過服務端得到;
- limit:每頁顯示條數,默認為10條;
- prev:自定義“上一頁”的內容,支持傳入普通文本和HTML;
- next:自定義“下一頁”的內容,支持傳入普通文本和HTML;
- theme:自定義主題,支持傳入顏色值或任意普通字符。
這里使用 layPage 來顯示分頁內容,而具體數據內容則需要使用 JS 來加載,具體代碼如下:

1 <script> 2 $(function () { 3 initPage(); 4 }); 5 6 function initPage(pageConf) { 7 if (!pageConf) { 8 pageConf = {}; 9 pageConf.pageSize = 10; 10 pageConf.currentPage = 1; 11 } 12 $.post("http://127.0.0.1:5000/get_data", pageConf, function (data) { 13 layui.use(['laypage', 'layer'], function () { 14 var page = layui.laypage; 15 page.render({ 16 elem: 'demo', 17 count: data.count, 18 curr: pageConf.currentPage, 19 limit: pageConf.pageSize, 20 first: "首頁", 21 last: "尾頁", 22 layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'], 23 jump: function (obj, first) { 24 if (!first) { 25 pageConf.currentPage = obj.curr; 26 pageConf.pageSize = obj.limit; 27 initPage(pageConf); 28 } 29 } 30 }); 31 fillTable(data["data"], (pageConf.currentPage - 1) * pageConf.pageSize); //頁面填充 32 }) 33 }); 34 } 35 36 //填充表格數據 37 function fillTable(data, num) { 38 $("#demoBody").html(''); 39 $.each(data, function (index, obj) { 40 // id 很多時候並不是連續的,如果為了顯示比較連續的記錄數,可以這樣根據當前頁和每頁條數動態的計算記錄序號 41 index = index + num + 1; 42 var info = ''; 43 info += '<tr>'; 44 info += '<td>' + index + '</td>'; 45 info += '<td>' + obj.id + '</td>'; 46 info += '<td>' + obj.name + '</td>'; 47 info += '</tr>'; 48 $("#demoBody").append(info); 49 }); 50 } 51 </script>
前端代碼完成了,還需要一個提供數據的接口,可以使用 Flask 定義一個路由來實現,例如:
1 @app.route('/get_data', methods=['POST']) 2 def get_data(): 3 sess = DBSession() 4 data = sess.query(t_students).all() 5 limit = int(request.form.get("pageSize")) 6 page = int(request.form.get("currentPage")) 7 start = (page - 1) * limit 8 end = page * limit if len(data) > page * limit else len(data) 9 ret = [{"id": data[i].stu_id, "name": data[i].stu_name} for i in range(start, end)] 10 return {"data": ret, "count": len(data)}
前端使用了 POST 請求,傳輸的數據包括當前頁數和每頁顯示條數,然后在 Flask 中使用 request.form.get() 來獲取數據,得到頁數和條數后取出相應區間中的數據,返回的結果是一個 JSON 格式數據,其中 data 表示數據,count 表示數據總條數。
最終得到的結果如下:
完整代碼已上傳到 GitHub!