request.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from typing import Any
  2. from pydantic import BaseModel, ConfigDict, Field
  3. from pydantic.alias_generators import to_camel
  4. from app.common.constant import RET
  5. from app.core.exceptions import CustomException
  6. class PageResultSchema(BaseModel):
  7. """分页查询结果模型"""
  8. model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
  9. page_no: int | None = Field(default=None, ge=1, description="页码,默认为1")
  10. page_size: int | None = Field(default=None, ge=1, description="页面大小,默认为10")
  11. total: int = Field(default=0, ge=0, description="总记录数")
  12. has_next: bool | None = Field(default=False, description="是否有下一页")
  13. items: list[Any] = Field(default_factory=list, description="分页后的数据列表")
  14. class PaginationService:
  15. """分页服务类(仅用于无法 SQL OFFSET/LIMIT 的数据源,如 Redis、本地文件列表、ORM 反射全量表名等)。"""
  16. @staticmethod
  17. async def paginate(
  18. data_list: list[Any],
  19. page_no: int | None = None,
  20. page_size: int | None = None,
  21. ) -> dict[str, Any]:
  22. """
  23. 对已在内存中的列表做切片分页。
  24. 关系型表列表请使用 CRUDBase.page(数据库分页)。
  25. 参数:
  26. - data_list (list[Any]): 原始数据列表。
  27. - page_no (int | None): 当前页码,默认 None。
  28. - page_size (int | None): 每页数据量,默认 None。
  29. 返回:
  30. - dict[str, Any]: 分页数据对象。
  31. 异常:
  32. - CustomException: 当分页参数不合法时抛出。
  33. """
  34. total = len(data_list)
  35. # 设置默认值
  36. if page_no is None:
  37. page_no = 1
  38. if page_size is None:
  39. page_size = 10
  40. # 验证分页参数
  41. if page_no < 1 or page_size < 1:
  42. raise CustomException(code=RET.ERROR.code, msg="分页参数不合法")
  43. # 计算起始索引和结束索引
  44. start = (page_no - 1) * page_size
  45. end = min(start + page_size, total)
  46. # 根据计算得到的起始索引和结束索引对数据列表进行切片
  47. paginated_data = data_list[start:end]
  48. # 判断是否有下一页
  49. has_next = end < total
  50. return {
  51. "items": paginated_data,
  52. "total": total,
  53. "page_no": page_no,
  54. "page_size": page_size,
  55. "has_next": has_next,
  56. }