3 fastAPI分页请求

在 FastAPI 中实现分页功能,可以结合数据库查询来返回数据的某一部分,而不是一次性加载所有数据。分页通常通过查询参数 skiplimit 来控制,skip 用于跳过前面的记录,limit 用于限制返回的记录数。下面是一个实现分页请求数据库中数据的示例,假设我们使用 SQLAlchemy 作为数据库 ORM 工具。


1. 安装依赖

如果还没有安装相关的依赖,首先需要安装 FastAPI、Uvicorn 和 SQLAlchemy。


pip install fastapi uvicorn sqlalchemy databases

2. 数据库模型和配置

在这个示例中,我们将使用 SQLAlchemy 来定义数据库模型,并使用 databases 包来进行异步数据库操作。

配置数据库连接和模型
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.future import select

# 配置数据库连接
DATABASE_URL = "sqlite+aiosqlite:///./test.db"  # 使用 SQLite 数据库

# 创建数据库连接引擎
engine = create_engine(DATABASE_URL, echo=True, future=True)

# 创建数据库会话
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, class_="AsyncSession")

# 创建模型基础类
Base = declarative_base()

# 定义数据模型
class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    price = Column(Integer)

# 创建数据库表
Base.metadata.create_all(bind=engine)

3. FastAPI 路由:分页查询

接下来,我们将通过 FastAPI 路由提供分页功能,通过 skiplimit 参数来控制分页请求。

创建分页查询的 API 路由
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from fastapi import FastAPI, Query, Depends
from typing import List

app = FastAPI()

# 获取数据库会话
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# 创建一个异步函数,支持分页查询
@app.get("/items/", response_model=List[Item])
async def read_items(skip: int = Query(0, alias="page", ge=0), limit: int = Query(10, le=100), db: AsyncSession = Depends(get_db)):
    # 使用 SQLAlchemy 查询数据库
    result = await db.execute(select(Item).offset(skip).limit(limit))
    items = result.scalars().all()  # 获取查询结果
    return items

4. 说明

  1. 分页参数
    • skip: 用于跳过前面的记录。skip 默认为 0,表示从第一个记录开始。
    • limit: 用于限制每次返回的数据条数。limit 默认为 10,最大限制为 100
  2. SQLAlchemy 异步查询
    • select(Item).offset(skip).limit(limit):这部分查询语句通过 SQLAlchemy 的 offsetlimit 来实现分页。
    • offset(skip):跳过前 skip 条数据。
    • limit(limit):限制返回 limit 条数据。
  3. 返回数据
    • 使用 .scalars().all() 来获取查询结果并返回为列表。

5. 启动应用

使用 Uvicorn 启动 FastAPI 应用:


uvicorn app:app --reload

6. 测试分页请求

假设你的数据库中有多条 Item 数据,你可以通过以下方式进行分页测试。

请求:获取第一页数据

GET /items/?page=0&limit=5

返回(假设返回 5 条数据):

[
  {"id": 1, "name": "Item 1", "price": 100},
  {"id": 2, "name": "Item 2", "price": 200},
  {"id": 3, "name": "Item 3", "price": 300},
  {"id": 4, "name": "Item 4", "price": 400},
  {"id": 5, "name": "Item 5", "price": 500}
]
请求:获取第二页数据json
GET /items/?page=1&limit=5

返回(假设返回的是第 6 到第 10 条数据):

[
  {"id": 6, "name": "Item 6", "price": 600},
  {"id": 7, "name": "Item 7", "price": 700},
  {"id": 8, "name": "Item 8", "price": 800},
  {"id": 9, "name": "Item 9", "price": 900},
  {"id": 10, "name": "Item 10", "price": 1000}
]

7. 进阶:实现分页的总数

为了更好地实现分页功能,除了返回当前页面的数据,还可以返回总记录数(即数据库中符合条件的数据总条数)。这样,前端可以知道总页数,从而进行分页导航。

修改分页查询,返回总数和总页数
from fastapi import HTTPException

@app.get("/items/", response_model=List[Item])
async def read_items(
    skip: int = Query(0, alias="page", ge=0),
    limit: int = Query(10, le=100),
    db: AsyncSession = Depends(get_db)
):
    # 查询数据总数
    result_count = await db.execute(select([Item]).with_only_columns([func.count()]))
    total_items = result_count.scalar()

    # 查询分页数据
    result = await db.execute(select(Item).offset(skip).limit(limit))
    items = result.scalars().all()

    # 返回数据及分页信息
    return {
        "items": items,
        "total_items": total_items,
        "total_pages": (total_items + limit - 1) // limit,
        "current_page": skip // limit + 1
    }
返回结果示例:
{
  "items": [
    {"id": 1, "name": "Item 1", "price": 100},
    {"id": 2, "name": "Item 2", "price": 200}
  ],
  "total_items": 50,
  "total_pages": 10,
  "current_page": 1
}

通过 FastAPI 和 SQLAlchemy,我们可以非常方便地实现分页查询。核心的操作包括使用 offsetlimit 来控制查询范围,以及通过查询参数 skiplimit 来控制分页。结合数据库的 count() 方法,还可以返回总记录数,进一步支持分页导航。

3 fastAPI分页请求_第1张图片

你可能感兴趣的:(python,FastAPI,fastapi)