You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask-SQLAlchemy 3.1调用paginate方法时出现AttributeError求助

问题

使用Flask 3.0.3和Flask-SQLAlchemy 3.1.1开发图书库项目,计划在index.html页面通过表格展示书籍标题、作者及ISBN信息,并通过paginate方法实现每页10条数据的分页展示。但执行语句book_data = books_query.paginate(page=page, per_page=per_page)时,触发AttributeError: 'Query' object has no attribute 'paginate'。

现有代码情况:

  • routes.py首页路由代码:
from flask import Blueprint, render_template, redirect, session, request
from books.database import Session
from books.models import Book, Author, Genre, Location, Publisher, Tag, Format

pages = Blueprint(
"pages", __name__, template_folder="templates", static_folder="static"
)

@pages.route("/")
def index():
    session = Session()

    # 获取查询参数中的页码
    page = request.args.get("page", 1, type=int)
    # 每页书籍数量
    per_page = 10  

    # 关联Book和Author表的查询
    books_query = session.query(
        Book.id,
        Book.title,
        Book.isbn,
        Author.first_name,
        Author.last_name
    ).join(Author, Author.id == Book.author_id)

    # 执行查询并分页
    book_data = books_query.paginate(page=page, per_page=per_page)

    # 关闭会话
    session.close()    

    return render_template(
        "index.html",
        title="Book Library",
        page_title="Library Catalog",
        book_data = book_data
    )
  • database.py会话创建代码:
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

load_dotenv()

# 配置数据库URL 
DATABASE_URI = os.environ.get('DATABASE_URI')

# 创建引擎
engine = create_engine(DATABASE_URI)

# 创建会话工厂
Session = sessionmaker(bind=engine)
  • requirements.txt依赖版本:
Flask==3.0.3
Flask-SQLAlchemy==3.1.1
SQLAlchemy==2.0.30

尝试合并查询与分页语句后仍报错;使用book_data = books_query.all()可正常获取所有数据,说明数据库连接无问题。查阅的旧版资料均基于db实例,而非当前用Session对象创建的会话实例,推测新版本分页实现存在差异。

解决方案

问题根源在于你使用了SQLAlchemy原生的Session对象,而paginate是Flask-SQLAlchemy封装的方法,原生SQLAlchemy的Query对象并不具备该方法。需改用Flask-SQLAlchemy提供的SQLAlchemy实例来管理数据库会话和执行查询。

1. 重构database.py

改用Flask-SQLAlchemy的SQLAlchemy类初始化数据库,替代原生SQLAlchemy的sessionmaker:

import os
from dotenv import load_dotenv
from flask_sqlalchemy import SQLAlchemy

load_dotenv()

db = SQLAlchemy()

def init_db(app):
    db_uri = os.environ.get('DATABASE_URI')
    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
    db.init_app(app)

2. 修改routes.py

使用Flask-SQLAlchemy提供的会话执行查询并调用paginate:

from flask import Blueprint, render_template, request
from books.database import db
from books.models import Book, Author

pages = Blueprint(
    "pages", __name__, template_folder="templates", static_folder="static"
)

@pages.route("/")
def index():
    # 获取查询参数中的页码
    page = request.args.get("page", 1, type=int)
    # 每页书籍数量
    per_page = 10  

    # 使用Flask-SQLAlchemy的查询接口调用paginate
    book_data = db.session.query(
        Book.id,
        Book.title,
        Book.isbn,
        Author.first_name,
        Author.last_name
    ).join(Author, Author.id == Book.author_id).paginate(page=page, per_page=per_page)

    return render_template(
        "index.html",
        title="Book Library",
        page_title="Library Catalog",
        book_data=book_data
    )

3. 应用初始化处补充数据库初始化

在Flask应用入口文件(如app.py)中调用init_db完成数据库初始化:

from flask import Flask
from books.database import init_db
from books.routes.pages import pages

app = Flask(__name__)
# 初始化数据库
init_db(app)
# 注册蓝图
app.register_blueprint(pages)

if __name__ == "__main__":
    app.run(debug=True)

补充说明

  • Flask-SQLAlchemy 3.x版本会自动管理会话生命周期,无需手动调用session.close(),请求结束后会话会自动关闭
  • paginate返回的对象包含分页所需属性:items(当前页数据)、page(当前页码)、pages(总页数)、per_page(每页数量)、total(总数据量)等,可直接在模板中使用这些属性渲染分页导航

内容的提问来源于stack exchange,提问作者wmiller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 16:29:53