FastAPI分页功能实现

FastAPI分页功能实现

在这里插入图片描述

分页功能实现

一、站在巨人的肩膀上(fastapi-pagination)

GitHub:https://github.com/uriyyo/fastapi-pagination

文档:https://uriyyo-fastapi-pagination.netlify.app/

二、安装fastapi-pagination

pip install fastapi-pagination

三、直接使用

from fastapi_pagination import Page, paginate, Params,add_pagination

  • Page:用于在路径中(response_model)声明返回模型
  • Params:用于提供分页参数
  • paginate:用于将数据进行分页

1. 使用依赖项

from fastapi import FastAPI, Depends
from fastapi_pagination import Page, paginate, add_pagination, Params
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    surname: str

users = [
    User(name='name', surname='name'),
    User(name='name2', surname='name'),
    User(name='name3', surname='name'),
    User(name='name4', surname='name'),
    User(name='name5', surname='name'),
    User(name='name6', surname='name'),
    User(name='name7', surname='name'),
    User(name='name8', surname='name'),
    User(name='name9', surname='name'),
    # ...
]

# 【response_model=Page[User]】在路径参数中声明响应数据类型
# 【params: Params = Depends()】把Params当做依赖项进行引入
@app.get('/users', response_model=Page[User])
async def get_users(params: Params = Depends()):
    # 将需要分页的数据进行分页,把params参数传入
    return paginate(users, params)

2. 省略依赖项

from fastapi import FastAPI, Depends
from fastapi_pagination import Page, paginate, add_pagination, Params
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    surname: str

users = [
    User(name='name', surname='name'),
    User(name='name2', surname='name'),
    User(name='name3', surname='name'),
    User(name='name4', surname='name'),
    User(name='name5', surname='name'),
    User(name='name6', surname='name'),
    User(name='name7', surname='name'),
    User(name='name8', surname='name'),
    User(name='name9', surname='name'),
    # ...
]

# 【response_model=Page[User]】在路径参数中声明响应数据类型
@app.get('/users', response_model=Page[User])
async def get_users():
    # 将需要分页的数据进行分页
    return paginate(users)
# 在接口函数之后,使用add_pagination进行默认添加分页依赖项
add_pagination(app)

四、Limit-Offset

from fastapi import FastAPI
from fastapi_pagination import LimitOffsetPage, add_pagination, paginate
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    surname: str

users = [
    User(name='name', surname='name'),
    User(name='name2', surname='name'),
    User(name='name3', surname='name'),
    User(name='name4', surname='name'),
    User(name='name5', surname='name'),
    User(name='name6', surname='name'),
    User(name='name7', surname='name'),
    User(name='name8', surname='name'),
    User(name='name9', surname='name'),
    # ...
]

@app.get('/users', response_model=LimitOffsetPage[User])
async def get_users():
    return paginate(users)

add_pagination(app)

五、自定义参数信息

1.自定义Params(把page参数起始值改为1)

from fastapi import Query
from fastapi_pagination.bases import AbstractParams, RawParams
from pydantic import BaseModel

class Params(BaseModel, AbstractParams):
    # 设置默认值为1,不能够小于1
    page: int = Query(1, ge=1, description="Page number")
    # 设置默认值为20,最大为100
    size: int = Query(20, gt=0, le=100, description="Page size")

    def to_raw_params(self) -> RawParams:
        return RawParams(
            limit=self.size,
            # 更爱page参数起始值从1开始
            offset=self.size * (self.page - 1),
        )

2.自定义Page模型

from __future__ import annotations

import math
from typing import TypeVar, Generic, Sequence
from fastapi_pagination.bases import AbstractPage

T = TypeVar("T")

class Page(AbstractPage[T], Generic[T]):
    # 修改Page模型
    data: Sequence[T] # 数据
    total: int # 总数据数
    page: int # 第n页
    size: int # 每页数量
    next: str # 下一页参数
    previous: str # 上一页参数
    total_pages: int # 总页数

    # 使用自定义的Params
    __params_type__ = Params  # Set params related to Page

    @classmethod
    def create(
            cls,
            items: data,
            total: int,
            params: Params,
    ) -> Page[T]:
        # 从params获取page和size
        page = params.page
        size = params.size
        # 通过总数和每页数量计算出总页数
        total_pages = math.ceil(total / params.size)
        # 生成下一页参数(如果没有下一页则为null)
        next = f"?page={page + 1}&size={size}" if (page + 1) <= total_pages else "null"
        # 生成上一页参数(如果没有上一页则为null)
        previous = f"?page={page - 1}&size={size}" if (page - 1) >= 1 else "null"

        # 根据定义的模型参数进行返回
        return cls(data=items, total=total, page=params.page,
                   size=params.size,
                   next=next,
                   previous=previous,
                   total_pages=total_pages)

3.重写整合(pagination.py)

from __future__ import annotations
import math
from typing import TypeVar, Generic, Sequence

from fastapi import Query
from fastapi_pagination.bases import AbstractPage, AbstractParams, RawParams
from pydantic import BaseModel

T = TypeVar("T")

class Params(BaseModel, AbstractParams):
    page: int = Query(1, ge=1, description="Page number")
    size: int = Query(20, gt=0, le=100, description="Page size")

    def to_raw_params(self) -> RawParams:
        return RawParams(
            limit=self.size,
            offset=self.size * (self.page - 1),
        )

class Page(AbstractPage[T], Generic[T]):
    results: Sequence[T]
    total: int
    page: int
    size: int
    next: str
    previous: str
    total_pages: int

    __params_type__ = Params  # Set params related to Page

    @classmethod
    def create(
            cls,
            results: results,
            total: int,
            params: Params,
    ) -> Page[T]:
        page = params.page
        size = params.size
        total_pages = math.ceil(total / params.size)
        next = f"?page={page + 1}&size={size}" if (page + 1) <= total_pages else "null"
        previous = f"?page={page - 1}&size={size}" if (page - 1) >= 1 else "null"

        return cls(results=results, total=total, page=params.page,
                   size=params.size,
                   next=next,
                   previous=previous,
                   total_pages=total_pages)

4.使用自定义后的分页功能

# 把Page从自定义的包中导入即可
from pagination import Page

@app.get('/users', response_model=Page[User])
async def get_users():
    return paginate(users)

六、集成SQLAlchemy使用

1、简单使用

1) 更改【paginate】包的路径为【fastapi_pagination.ext.sqlalchemy】
from fastapi_pagination.ext.sqlalchemy import paginate
2) 创建数据返回模型
class User(BaseModel):
    email: str
    password: str
    is_active: bool

    # 这个配置必须得要
    class Config:
        orm_mode = True

3) 使用【sqlalchemy.paginate】
# 【db: Session = Depends(get_db)】:数据库依赖项
@app.get('/users', response_model=Page[User])
async def get_users(db: Session = Depends(get_db)):
    # 此处的参数为【db.query(models.User)】
    # 【sqlalchemy.paginate】的参数为【sqlalchemy.orm.query.Query】类型
    return paginate(db.query(models.User))

2、使用异步

1)安装支持异步的aiomysql
pip install aiomysql

2)sqlalchemy引擎需要异步创建
from sqlalchemy.ext.asyncio import create_async_engine

# 这里要使用支持异步的aiomysql
SQLALCHEMY_DATABASE_URL = "mysql+aiomysql://root:123456@127.0.0.1:3306/users?charset=utf8"
# 注意sqlite不支持异步
engine = create_async_engine(SQLALCHEMY_DATABASE_URL)

3)创建异步的数据库会话
from sqlalchemy.ext.asyncio import AsyncSession

SessionLocal = sessionmaker(bind=engine, class_=AsyncSession)

4)创建异步的数据库依赖项
# 依赖项要定义为异步函数
async def get_db():
    async with SessionLocal() as session:
        yield session

5)paginate使用async_sqlalchemy模块下的
from fastapi_pagination.ext.async_sqlalchemy import paginate
from sqlalchemy.future import select

@app.get('/users', response_model=Page[User])
async def get_users(db: Session = Depends(get_db)):
    # 第一个参数为数据库连接
    # 第二个参数为Select类型的参数
    # 要添加await关键字
    return await paginate(db, select(models.User))

七、演示

在这里插入图片描述

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Flask是一个微型Python Web框架,使用render_pagination可以在Web应用程序中实现分页功能。 使用方法如下: 1. 在模板文件中使用render_template()函数渲染页面,并传入分页数据。 2. 在模板文件中使用render_pagination()函数生成分页导航条。 3. 在视图函数中,对数据进行分页处理,并传入到模板文件中。 举个例子: ```python from flask import Flask, render_template from flask_paginate import Pagination, get_page_args app = Flask(__name__) @app.route('/') def index(): search = False q = request.args.get('q') if q: search = True page, per_page, offset = get_page_args(page_parameter='page', per_page_parameter='per_page') total = len(items) pagination_items = items[offset: offset + per_page] pagination = Pagination(page=page, per_page=per_page, total=total, css_framework='bootstrap4') return render_template('index.html', items=pagination_items, page=page, per_page=per_page, pagination=pagination, search=search, q=q) if __name__ == '__main__': app.run() ``` 模板文件 ```html <table> {% for item in items %} <tr> <td>{{ item.name }}</td> </tr> {% endfor %} </table> {{ pagination.render() }} ``` 在上面的例子中,我们使用了`flask-paginate`这个包来实现分页, 在视图函数中调用get_page_args()函数来获取当前页码,每页显示数量,和偏移量。 然后使用`Pagination`这个类来初始化分页导航条 ### 回答2: Flask中的render_pagination是一个用于生成分页导航的方法。它可以方便地将分页相关的HTML代码嵌入到模板中。 使用render_pagination的步骤如下: 1. 导入flask模块中的render_pagination方法:from flask_paginate import render_pagination 2. 设置分页导航相关的参数,包括总的条目数(total),每页显示的条目数量(per_page),当前页码(page),以及用于生成链接的回调函数(endpoint)等。 3. 调用render_pagination方法,将以上设置的参数传入,并将返回的分页导航代码嵌入到模板中。 具体的示例代码如下: 1. 在Python文件中设置分页导航相关的参数: ```python from flask import Flask, render_template from flask_paginate import Pagination app = Flask(__name__) @app.route('/') def index(): page = int(request.args.get('page', 1)) per_page = 10 total = 100 pagination = Pagination(page=page, per_page=per_page, total=total, css_framework='bootstrap4') # 将分页导航代码嵌入到模板中 return render_template('index.html', pagination=pagination) ``` 2. 在模板文件中将分页导航代码渲染到页面中: ```html <!DOCTYPE html> <html> <head> <title>Flask Pagination Example</title> </head> <body> <h1>Flask Pagination Example</h1> <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul> <!-- 分页导航代码 --> {{ pagination.info }} {{ pagination.links }} </body> </html> ``` 这样,当访问首页时,会根据设置的总条目数和每页显示的条目数量自动生成合适的分页导航,并将其渲染到模板中的适当位置。 ### 回答3: Flask是一个Python的轻量级Web框架,可以用来构建简单的网站或Web应用程序。而render_pagination是Flask框架中的一个内置函数,用于在网页中实现分页功能。 使用render_pagination函数,首先需要导入相应的模块,一般是`from flask import render_template`。然后在路由函数中,根据需要的分页参数进行设置,通常包括当前页、每页显示的条目数量、总页数、总条目数等。 假设需要在一个博客网站中实现分页功能,可以使用render_pagination函数来展示博客文章列表。首先需要确定每页显示的博客数量,可以使用Flask框架中的request.args来获取当前页码数。在此基础上,根据数据的总条目数计算总页数,并将需要展示的博客列表传递给render_pagination函数。 示例代码如下: ```python from flask import Flask, render_template, request from flask_paginate import Pagination app = Flask(__name__) @app.route('/') def index(): page = int(request.args.get('page', 1)) per_page = 10 # 每页显示的博客数量 total = 100 # 博客的总条目数 blogs = [] # 博客列表,可以是从数据库中查询得到的数据 start = (page-1) * per_page end = start + per_page pagination = Pagination(page=page, per_page=per_page, total=total) return render_template('index.html', blogs=blogs[start:end], pagination=pagination) if __name__ == '__main__': app.run(debug=True) ``` 在index.html模板文件中,可以使用pagination的属性和方法来生成分页导航,例如`{{ pagination.links }}`可以生成展示分页导航链接的HTML代码。 通过上述代码,当访问http://localhost:5000/时,会显示第一页的博客列表,并在页面底部显示分页导航。点击不同的页码,可以切换显示不同页的博客列表。 总的来说,Flask的render_pagination函数是一个方便的工具,用于在网页中实现分页功能,可以根据具体需要进行定制和扩展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值