79 lines
2.1 KiB
Python
79 lines
2.1 KiB
Python
"""
|
|
通用响应格式 Schema
|
|
==================
|
|
|
|
与前端 ApiResponse<T> 保持一致:
|
|
{ code: number; data: T; message: string }
|
|
"""
|
|
|
|
from typing import Any, Generic, TypeVar
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class ApiResponse(BaseModel, Generic[T]):
|
|
"""
|
|
统一 API 响应格式
|
|
|
|
Attributes:
|
|
code: HTTP 状态码(200 表示成功)
|
|
data: 响应数据(泛型)
|
|
message: 提示信息
|
|
"""
|
|
|
|
code: int = Field(default=200, description="状态码,200 表示成功")
|
|
data: T | None = Field(default=None, description="响应数据")
|
|
message: str = Field(default="success", description="提示信息")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"code": 200,
|
|
"data": {},
|
|
"message": "success",
|
|
}
|
|
}
|
|
|
|
|
|
class PaginatedData(BaseModel, Generic[T]):
|
|
"""分页数据包装"""
|
|
|
|
items: list[T] = Field(description="数据列表")
|
|
total: int = Field(description="总数")
|
|
page: int = Field(description="当前页码")
|
|
page_size: int = Field(description="每页数量")
|
|
has_more: bool = Field(description="是否有更多")
|
|
|
|
|
|
class PaginationParams(BaseModel):
|
|
"""分页请求参数"""
|
|
|
|
page: int = Field(default=1, ge=1, description="页码")
|
|
page_size: int = Field(default=20, ge=1, le=100, description="每页数量")
|
|
|
|
@property
|
|
def offset(self) -> int:
|
|
return (self.page - 1) * self.page_size
|
|
|
|
|
|
class ApiErrorResponse(BaseModel):
|
|
"""错误响应格式"""
|
|
|
|
code: int = Field(description="错误码")
|
|
message: str = Field(description="错误信息")
|
|
detail: dict[str, Any] | None = Field(default=None, description="详细错误信息")
|
|
|
|
|
|
def success_response(data: T | None = None, message: str = "success") -> ApiResponse[T]:
|
|
"""构造成功响应"""
|
|
return ApiResponse(code=200, data=data, message=message)
|
|
|
|
|
|
def error_response(
|
|
code: int, message: str, detail: dict[str, Any] | None = None
|
|
) -> ApiErrorResponse:
|
|
"""构造错误响应"""
|
|
return ApiErrorResponse(code=code, message=message, detail=detail)
|