SQLAlchemy 超简单的分页查询

在 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)

分页请求列表

如果对你有帮助, 请点赞+关注鼓励下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值