mirror of
https://github.com/fastapi-practices/fastapi_best_architecture.git
synced 2025-08-18 15:00:46 +08:00

* Use env to manage important configurations and distinguish environments * fix Pydantic validation error caused by None value in links field of Page class * Production environment no longer exposes API docs * Extract TOKEN_URL to conf
69 lines
2.0 KiB
Python
69 lines
2.0 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
|
||
)
|