在 Flask 中使用 SQLAlchemy 进行分页查询是常见的需求,特别是当你需要显示大量数据时。分页的主要目的是避免一次性加载所有数据,从而提高性能和用户体验。
SQLAlchemy特点
- 数据库抽象: 支持多种数据库系统,代码移植性好。
- 灵活: 既可以用作低级 SQL 表达式语言,也可以用作全功能的 ORM。
- 强大的查询构建: 提供了丰富的 API 来构建复杂的查询。
- 会话管理: 负责数据库连接、事务管理等。
- 与 Web 框架良好集成: 虽然不是 Flask 独有,但与 Flask 和 Django 等 Web 框架集成紧密。
安装
pip install SQLAlchemy Flask-SQLAlchemy
查看安装包并生成文件
pip list
pip freeze -> requirements
如何在Flask中进行分页查询
核心思想是使用 SQL 的 LIMIT 和 OFFSET 子句(或者 SQLAlchemy 对应的 .limit() 和 .offset() 方法)来获取结果集的子集。
- SQLAlchemy 模块引入使用(app/app.py)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# 创建扩展对象
db = SQLAlchemy()
def create_app(config_name=None):
# 创建 Flask 应用程序实例
app = Flask(__name__)
# 加载配置
if config_name is None:
app.config.from_object('config.DevelopmentConfig') # 默认加载开发环境配置
else:
app.config.from_object(f'config.{config_name}') # 根据参数加载配置
# 初始化扩展
db.init_app(app)
return app
- 模型设置(app/models/user.py)
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
# 用户表
class User(db.Model):
# 表名
__tablename__ = 'users'
# 字段定义
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(10))
user_id = db.Column(db.String(120))
email = db.Column(db.String(20))
phone = db.Column(db.String(11))
avatar = db.Column(db.String(100))
def __repr__(self):
return f'<User {self.username}>'
- 方法1: 使用 SQLAlchemy 的 .limit() 和 .offset() (更底层)
这种方法需要手动计算 offset 并获取总记录数, 当然我是没用这种方式了。
@app.route('/list')
def list_users():
page = request.args.get('page', 1, type=int) # 从请求参数获取页码,默认为1
per_page = 10 # 每页显示的条目数
# 计算偏移量
offset = (page - 1) * per_page
# 查询当前页的数据
users_on_page = User.query.limit(per_page).offset(offset).all()
# 获取总记录数 (需要执行一次额外的查询)
total_users = User.query.count()
# 计算总页数
total_pages = (total_users + per_page - 1) // per_page
- 方法2: 使用 Flask-SQLAlchemy 的 .paginate() 方法 (推荐)
paginate 返回的属性使用
属性 | 用法 |
---|---|
items | 当前页的记录列表 |
page | 当前页码 |
per_page | 每页条目数 |
total | 总记录数 |
pages | 总页数 |
has_next | 是否有下一页(布尔值) |
has_prev | 是否有上一页(布尔值) |
代码示例(app/routes/admin/user.py):
# 查询用户
@user_bp.route('/list', methods=['POST'])
@validate_model(UserListModel)
def get_users(page_index, page_size):
data = User.query.paginate(page=page_index, per_page=page_size, error_out=False)
if not data.items:
return success_response({
"list": []
})
# 数据系列化处理, 返回指定的内容
lists = [dict(
username=user.username,
email=user.email,
avatar = user.avatar,
phone = user.phone,
user_id = user.user_id,
) for user in data.items]
res = {
"list": lists,
"total": data.total,
"page_index": data.page,
"page_size": data.per_page,
}
# 这里进行了封装
return success_response(res)
如果对你有帮助, 请点赞+关注鼓励下