from typing import Generic, Optional, Sequence, TypeVar import math from fastapi import Query from pydantic import BaseModel from tortoise.queryset import QuerySet T = TypeVar("T") class PaginationPydantic(BaseModel, Generic[T]): """分页模型""" status_code: int = 200 message: str = "Success" total: int page: int size: int total_pages: int data: Sequence[T] class Params(BaseModel): """传参""" # 设置默认值为1,不能够小于1 page: int = Query(1, ge=1, description="Page number") # 设置默认值为10,最大为100 size: int = Query(10, gt=0, le=200, description="Page size") # 默认值None表示选传 order_by: Optional[str] = Query(None, max_length=32, description="Sort key") async def pagination(pydantic_model, query_set: QuerySet, params: Params, callback=None): """分页响应""" """ pydantic_model: Pydantic model query_set: QuerySet params: Params callback: if you want to do something for query_set,it will be useful. """ page: int = params.page size: int = params.size order_by: str = params.order_by total = await query_set.count() # 通过总数和每页数量计算出总页数 total_pages = math.ceil(total / size) if page > total_pages and total: # 排除查询集为空时报错,即total=0时 raise ValueError("页数输入有误") # 排序后分页 if order_by: order_by = order_by.split(',') query_set = query_set.order_by(*order_by) # 分页 query_set = query_set.offset((page - 1) * size) # 页数 * 页面大小=偏移量 query_set = query_set.limit(size) if callback: """对查询集操作""" query_set = await callback(query_set) # query_set = await query_set data = await pydantic_model.from_queryset(query_set) return PaginationPydantic(**{ "total": total, "page": page, "size": size, "total_pages": total_pages, "data": data, })