在Flask项目中使用SQLAlchemy操作数据库时,实现列表分页不需要手动计算数据偏移量和总页数,直接调用SQLAlchemy查询对象自带的paginate方法就能快速完成分页逻辑开发,大幅降低分页功能的实现复杂度。

环境准备
首先确保项目中已经安装好Flask和Flask-SQLAlchemy扩展,如果还未安装可以通过pip命令完成安装:
pip install flask flask-sqlalchemy
接着在Flask应用中初始化SQLAlchemy实例,定义基础的模型类,以下是简单的初始化示例:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库连接,这里使用SQLite作为示例
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 定义用户模型作为示例数据表
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
age = db.Column(db.Integer)
paginate对象的基本使用
SQLAlchemy的查询对象提供了paginate方法,该方法接收三个核心参数:当前页码、每页显示的数据条数、是否返回错误。调用后会返回一个分页对象,该对象包含了分页所需的全部数据和相关属性。
以下是基础的分页查询示例:
from flask import request
@app.route('/user/list')
def user_list():
# 获取前端传递的页码参数,默认值为1
page = request.args.get('page', 1, type=int)
# 每页显示10条数据
per_page = 10
# 调用paginate方法获取分页对象
pagination = User.query.paginate(page=page, per_page=per_page, error_out=False)
# 获取当前页的数据列表
user_list = pagination.items
return {
'users': [{'id': u.id, 'username': u.username, 'age': u.age} for u in user_list],
'total': pagination.total,
'pages': pagination.pages,
'current_page': pagination.page
}
paginate对象常用属性说明
paginate方法返回的分页对象包含多个实用属性,开发者可以根据需求直接使用这些属性完成分页相关的逻辑处理,常用属性如下:
| 属性名 | 说明 |
|---|---|
| items | 当前页的数据列表,类型为查询模型对应的对象列表 |
| page | 当前页码,类型为整型 |
| per_page | 每页显示的数据条数,类型为整型 |
| total | 符合条件的总数据条数,类型为整型 |
| pages | 总页数,根据total和per_page自动计算,类型为整型 |
| has_prev | 是否存在上一页,存在则返回True,否则返回False |
| has_next | 是否存在下一页,存在则返回True,否则返回False |
| prev_num | 上一页的页码,不存在则返回None |
| next_num | 下一页的页码,不存在则返回None |
结合前端实现完整分页
后端返回分页相关数据后,前端可以根据这些数据渲染分页导航栏,以下是简单的前端页面示例,使用HTML和原生JavaScript实现分页展示:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>用户列表分页</title>
</head>
<body>
<h3>用户列表</h3>
<ul id="userList"></ul>
<div id="pagination"></div>
<script>
// 获取当前页面URL中的page参数
function getQueryParam(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
// 当前页码,默认1
let currentPage = parseInt(getQueryParam('page')) || 1;
// 请求后端数据
fetch(`/user/list?page=${currentPage}`)
.then(res => res.json())
.then(data => {
// 渲染用户列表
const userList = document.getElementById('userList');
data.users.forEach(user => {
const li = document.createElement('li');
li.textContent = `ID:${user.id},用户名:${user.username},年龄:${user.age}`;
userList.appendChild(li);
});
// 渲染分页导航
const pagination = document.getElementById('pagination');
if (data.current_page > 1) {
const prevLink = document.createElement('a');
prevLink.href = `/user/list?page=${data.current_page - 1}`;
prevLink.textContent = '上一页';
pagination.appendChild(prevLink);
}
for (let i = 1; i <= data.pages; i++) {
const pageLink = document.createElement('a');
pageLink.href = `/user/list?page=${i}`;
pageLink.textContent = i;
if (i === data.current_page) {
pageLink.style.fontWeight = 'bold';
}
pagination.appendChild(pageLink);
}
if (data.current_page < data.pages) {
const nextLink = document.createElement('a');
nextLink.href = `/user/list?page=${data.current_page + 1}`;
nextLink.textContent = '下一页';
pagination.appendChild(nextLink);
}
});
</script>
</body>
</html>
注意事项
- paginate方法的error_out参数如果设置为True,当请求的页码超过总页数时会返回404错误,设置为False则会返回空的数据列表,实际开发中建议根据需求选择。
- 如果查询需要添加过滤条件,只需要在调用paginate之前添加filter等查询条件即可,例如
User.query.filter(User.age > 18).paginate(page=page, per_page=per_page, error_out=False)。 - 每页显示条数per_page建议根据页面展示需求合理设置,避免单页数据过多导致页面加载缓慢。
PythonFlaskSQLAlchemypaginate分页修改时间:2026-07-03 18:00:33