Files
fastapi-best-architecture/backend/app/common/pagination.py
T

62 lines
1.9 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import math
from typing import TypeVar, Generic, Sequence, Dict, Union
from fastapi import Query
from fastapi_pagination.bases import AbstractPage, AbstractParams, RawParams
from fastapi_pagination.links.bases import create_links
from pydantic import BaseModel
T = TypeVar('T')
"""
重写分页库:fastapi-pagination
使用方法:example link: https://github.com/uriyyo/fastapi-pagination/tree/main/examples
"""
class Params(BaseModel, AbstractParams):
page: int = Query(1, ge=1, description='Page number')
size: int = Query(20, gt=0, le=100, description='Page size') # 默认 20 条记录
def to_raw_params(self) -> RawParams:
return RawParams(
limit=self.size,
offset=self.size * (self.page - 1),
)
class Page(AbstractPage[T], Generic[T]):
data: Sequence[T] # 数据
total: int # 总数据数
page: int # 第n页
size: int # 每页数量
total_pages: int # 总页数
links: Dict[str, Union[str, None]] # 跳转链接
__params_type__ = Params # 使用自定义的Params
@classmethod
def create(
cls,
data: Sequence[T],
total: int,
params: Params,
) -> Page[T]:
page = params.page
size = params.size
total_pages = math.ceil(total / params.size)
links = create_links(
**{
'first': {'page': 1, 'size': f'{size}'},
'last': {'page': f'{math.ceil(total / params.size)}', 'size': f'{size}'} if total > 0 else None,
'next': {'page': f'{page + 1}', 'size': f'{size}'} if (page + 1) <= total_pages else None,
'prev': {'page': f'{page - 1}', 'size': f'{size}'} if (page - 1) >= 1 else None,
}
).dict()
return cls(data=data, total=total, page=params.page, size=params.size, total_pages=total_pages, links=links)