From 42943f9967db1e3e101081e48866d436750e541a Mon Sep 17 00:00:00 2001 From: aaron <> Date: Fri, 21 Mar 2025 23:22:54 +0800 Subject: [PATCH] update --- .env.example | 3 + README.md | 50 +++++++++- app/exceptions/http_exception.py | 142 ++++++++++++++--------------- app/main.py | 21 ++++- app/middleware.py | 66 ++++++++++++++ app/middleware/response_wrapper.py | 14 +++ app/models/__init__.py | 2 +- app/models/api_response.py | 27 ++++++ app/routers/dress_router.py | 81 ++++++++++------ app/routers/tryon_router.py | 13 +-- app/schemas/dress.py | 12 +-- app/utils/response.py | 120 ++++++++++++------------ 12 files changed, 372 insertions(+), 179 deletions(-) create mode 100644 app/middleware.py create mode 100644 app/models/api_response.py diff --git a/.env.example b/.env.example index ae22320..8164745 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,9 @@ HOST=0.0.0.0 PORT=9001 DEBUG=true +# API响应格式配置 +USE_STANDARD_RESPONSE=1 + # 数据库配置 DB_HOST=localhost DB_PORT=3306 diff --git a/README.md b/README.md index 9ff3db9..42a535c 100644 --- a/README.md +++ b/README.md @@ -235,13 +235,59 @@ docker exec -it ai-dressing-app bash -c "env | sort" - 敏感信息应通过环境变量或Docker secrets进行管理 - 建议将`.env`文件添加到`.gitignore`中,避免意外提交 -## API 文档 +## API接口文档 -启动服务后,访问以下地址查看自动生成的 API 文档: +服务启动后,可通过以下地址访问API文档: - Swagger UI: http://localhost:9001/docs - ReDoc: http://localhost:9001/redoc +## API响应格式 + +系统支持两种API响应格式,可以通过环境变量进行配置: + +### 标准响应格式 (USE_STANDARD_RESPONSE=1) + +所有API接口都会返回统一的标准格式: + +```json +{ + "code": 200, + "message": "操作成功", + "data": { ... } +} +``` + +错误响应示例: + +```json +{ + "code": 400, + "message": "请求参数错误", + "data": null +} +``` + +### 简洁响应格式 (USE_STANDARD_RESPONSE=0) + +API接口直接返回数据,不包含额外的包装: + +```json +{ ... } // 直接返回业务数据 +``` + +错误响应仍然保持标准格式,以确保错误信息清晰: + +```json +{ + "code": 400, + "message": "请求参数错误", + "data": null +} +``` + +> 注意:健康检查端点 `/health` 和 `/` 始终返回简洁格式,不受环境变量影响。 + ## 主要 API 端点 ### 大模型对话 diff --git a/app/exceptions/http_exception.py b/app/exceptions/http_exception.py index cbf6309..f3e84d8 100644 --- a/app/exceptions/http_exception.py +++ b/app/exceptions/http_exception.py @@ -1,90 +1,82 @@ -from fastapi import FastAPI, Request, status +from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from fastapi.exceptions import RequestValidationError from starlette.exceptions import HTTPException as StarletteHTTPException +import os +import traceback import logging -from typing import Any, Dict, Optional, Union -from app.utils.response import APIResponse +from app.models.api_response import APIResponseModel +# 根据环境变量决定是否使用标准响应格式 +use_standard_response = os.environ.get("USE_STANDARD_RESPONSE") == "1" logger = logging.getLogger(__name__) class CustomHTTPException(Exception): - """自定义HTTP异常""" - - def __init__( - self, - status_code: int = 400, - code: int = None, - message: str = "操作失败", - data: Any = None - ): + """自定义HTTP异常类,用于抛出自定义的HTTP错误""" + def __init__(self, status_code: int, detail: str = None): self.status_code = status_code - self.code = code or status_code - self.message = message - self.data = data - super().__init__(self.message) + self.detail = detail -def setup_exception_handlers(app: FastAPI) -> None: - """设置FastAPI应用的异常处理程序""" +async def http_exception_handler(request: Request, exc: CustomHTTPException): + """处理自定义HTTP异常的处理器""" + logger.error(f"HTTP错误: {exc.status_code} - {exc.detail}") - @app.exception_handler(CustomHTTPException) - async def custom_http_exception_handler(request: Request, exc: CustomHTTPException): - """处理自定义HTTP异常""" - logger.error(f"自定义HTTP异常: {exc.message} (状态码: {exc.status_code}, 业务码: {exc.code})") - return JSONResponse( - status_code=exc.status_code, - content=APIResponse.error( - message=exc.message, - code=exc.code, - data=exc.data - ) - ) + return JSONResponse( + status_code=exc.status_code, + content=APIResponseModel( + code=exc.status_code, + message=exc.detail or "请求处理失败" + ).dict() + ) + +async def starlette_exception_handler(request: Request, exc: StarletteHTTPException): + """处理FastAPI内置的HTTP异常的处理器""" + logger.error(f"Starlette HTTP错误: {exc.status_code} - {exc.detail}") - @app.exception_handler(StarletteHTTPException) - async def http_exception_handler(request: Request, exc: StarletteHTTPException): - """处理标准HTTP异常""" - logger.error(f"HTTP异常: {exc.detail} (状态码: {exc.status_code})") - return JSONResponse( - status_code=exc.status_code, - content=APIResponse.error( - message=str(exc.detail), - code=exc.status_code - ) - ) + return JSONResponse( + status_code=exc.status_code, + content=APIResponseModel( + code=exc.status_code, + message=str(exc.detail) + ).dict() + ) + +async def validation_exception_handler(request: Request, exc: RequestValidationError): + """处理请求验证错误的处理器""" + error_detail = exc.errors() + error_messages = [f"{e['loc'][-1]}: {e['msg']}" for e in error_detail] + error_message = ", ".join(error_messages) + logger.error(f"请求验证错误: {error_message}") - @app.exception_handler(RequestValidationError) - async def validation_exception_handler(request: Request, exc: RequestValidationError): - """处理请求验证异常""" - error_details = exc.errors() - error_messages = [] - - for error in error_details: - location = " -> ".join(str(loc) for loc in error["loc"]) - message = f"{location}: {error['msg']}" - error_messages.append(message) - - error_message = "; ".join(error_messages) - logger.error(f"验证错误: {error_message}") - - return JSONResponse( - status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, - content=APIResponse.error( - message="请求参数验证失败", - code=status.HTTP_422_UNPROCESSABLE_ENTITY, - data={"details": error_details} - ) - ) + return JSONResponse( + status_code=422, + content=APIResponseModel( + code=422, + message=f"请求参数验证失败: {error_message}", + data=error_detail + ).dict() + ) + +async def general_exception_handler(request: Request, exc: Exception): + """处理一般性异常的处理器""" + # 记录详细的错误信息 + error_msg = str(exc) + logger.error(f"服务器错误: {error_msg}") + logger.error(traceback.format_exc()) - @app.exception_handler(Exception) - async def general_exception_handler(request: Request, exc: Exception): - """处理通用异常""" - logger.exception(f"未处理的异常: {str(exc)}") - return JSONResponse( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - content=APIResponse.error( - message="服务器内部错误", - code=status.HTTP_500_INTERNAL_SERVER_ERROR, - data={"detail": str(exc)} if app.debug else None - ) - ) \ No newline at end of file + return JSONResponse( + status_code=500, + content=APIResponseModel( + code=500, + message="服务器内部错误", + data={"detail": error_msg} if os.environ.get("DEBUG") == "1" else None + ).dict() + ) + +def setup_exception_handlers(app: FastAPI): + """为FastAPI应用设置所有异常处理器""" + app.add_exception_handler(CustomHTTPException, http_exception_handler) + app.add_exception_handler(StarletteHTTPException, starlette_exception_handler) + app.add_exception_handler(RequestValidationError, validation_exception_handler) + app.add_exception_handler(Exception, general_exception_handler) \ No newline at end of file diff --git a/app/main.py b/app/main.py index 83492ae..ea4c3ef 100644 --- a/app/main.py +++ b/app/main.py @@ -24,6 +24,10 @@ logging.basicConfig( ) logger = logging.getLogger(__name__) +# 全局配置:是否使用标准响应格式,默认禁用直接返回数据 +os.environ["USE_STANDARD_RESPONSE"] = os.environ.get("USE_STANDARD_RESPONSE", "0") +logger.info(f"标准响应格式: {'已启用' if os.environ['USE_STANDARD_RESPONSE'] == '1' else '已禁用'}") + app = FastAPI( title="AI-Dressing API", description="基于 DashScope 的 AI 服务 API", @@ -53,7 +57,7 @@ app.include_router(tryon_router.router, prefix="/api/tryons", tags=["试穿"]) @app.get("/", tags=["健康检查"]) async def root(): """API 根端点""" - return APIResponse.ok(message="服务运行中") + return {"message": "服务运行中"} @app.get("/health", tags=["健康检查"]) async def health_check(): @@ -86,9 +90,17 @@ async def health_check(): health_data["checks"]["qcloud"] = {"status": "missing", "message": "腾讯云凭证未配置"} if health_status == "healthy": - return APIResponse.ok(data=health_data, message=health_message) + return { + "status": health_status, + "message": health_message, + "data": health_data + } else: - return APIResponse.error(message=health_message, code=503, data=health_data) + return { + "status": health_status, + "message": health_message, + "data": health_data + } @app.get("/info", tags=["服务信息"]) async def get_info(): @@ -98,8 +110,9 @@ async def get_info(): "app_name": "AI-Dressing API", "version": "0.1.0", "debug_mode": settings.debug, + "standard_response": os.environ.get("USE_STANDARD_RESPONSE") == "1" } - return APIResponse.ok(data=info_data, message="服务信息获取成功") + return info_data if __name__ == "__main__": import uvicorn diff --git a/app/middleware.py b/app/middleware.py new file mode 100644 index 0000000..0aa882d --- /dev/null +++ b/app/middleware.py @@ -0,0 +1,66 @@ +from fastapi import Request +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.responses import Response, JSONResponse +import json +import os + +from app.models.api_response import APIResponseModel +from app.utils.response import APIResponse + +class ResponseWrapperMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request: Request, call_next): + # 检查是否需要启用标准响应包装 + use_standard_response = os.environ.get("USE_STANDARD_RESPONSE") == "1" + + # 不包装的情况:健康检查端点或禁用了标准响应 + health_endpoints = ["/health", "/"] + if request.url.path in health_endpoints or not use_standard_response: + return await call_next(request) + + response = await call_next(request) + + # 如果响应已经被包装或者是文件下载等特殊响应,则不再处理 + if ( + isinstance(response, Response) + and not isinstance(response, JSONResponse) + or response.headers.get("content-type") != "application/json" + ): + return response + + # 处理JSON响应 + try: + response_body = [section async for section in response.body_iterator] + response.body_iterator = None + + if len(response_body) > 0: + body = response_body[0].decode() + json_body = json.loads(body) + + # 检查是否已经是标准格式 + if isinstance(json_body, dict) and "code" in json_body and "data" in json_body and "message" in json_body: + # 已经是标准格式,直接返回 + new_response = Response( + content=body, + status_code=response.status_code, + headers=dict(response.headers), + media_type=response.media_type + ) + return new_response + + # 包装响应 + api_response = APIResponseModel( + code=200, + message="操作成功", + data=json_body + ) + + return JSONResponse( + content=api_response.dict(), + status_code=response.status_code, + headers=dict(response.headers), + ) + + return response + except Exception as e: + # 如果解析失败,返回原始响应 + return response \ No newline at end of file diff --git a/app/middleware/response_wrapper.py b/app/middleware/response_wrapper.py index 7ac716b..b3d2b3f 100644 --- a/app/middleware/response_wrapper.py +++ b/app/middleware/response_wrapper.py @@ -3,6 +3,9 @@ from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware from typing import Any, Dict, Optional, Union import json +import os + +from app.utils.response import APIResponse class ResponseWrapperMiddleware(BaseHTTPMiddleware): """ @@ -14,11 +17,22 @@ class ResponseWrapperMiddleware(BaseHTTPMiddleware): "message": "操作成功", "data": 原始响应数据 } + + 可以通过设置环境变量USE_STANDARD_RESPONSE=0来禁用标准响应格式 """ + def __init__(self, app): + super().__init__(app) + # 从环境变量中读取是否启用标准响应格式 + self.use_standard_response = os.environ.get("USE_STANDARD_RESPONSE", "1") == "1" + async def dispatch( self, request: Request, call_next ) -> Response: + # 如果禁用了标准响应,直接返回原始响应 + if not self.use_standard_response: + return await call_next(request) + # 排除不需要包装的路径 if self._should_skip_path(request.url.path): return await call_next(request) diff --git a/app/models/__init__.py b/app/models/__init__.py index 0519ecb..df1d76e 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -1 +1 @@ - \ No newline at end of file +from app.models.api_response import APIResponseModel, PaginatedResponseModel \ No newline at end of file diff --git a/app/models/api_response.py b/app/models/api_response.py new file mode 100644 index 0000000..c26e19d --- /dev/null +++ b/app/models/api_response.py @@ -0,0 +1,27 @@ +from typing import Any, Dict, List, Optional, Union, ClassVar +from pydantic import BaseModel, Field +from datetime import datetime + +class APIResponseModel(BaseModel): + """API响应基础模型""" + code: int = Field(200, description="业务状态码") + message: str = Field("操作成功", description="响应消息") + data: Optional[Any] = Field(None, description="响应数据") + + class Config: + """模型配置""" + arbitrary_types_allowed = True + json_encoders = { + datetime: lambda dt: dt.isoformat() + } + +class PaginatedResponseModel(BaseModel): + """分页响应模型""" + items: List[Any] = Field(..., description="数据项列表") + total: int = Field(..., description="总数据量") + page: int = Field(1, description="当前页码") + size: int = Field(10, description="每页数据量") + + class Config: + """模型配置""" + arbitrary_types_allowed = True \ No newline at end of file diff --git a/app/routers/dress_router.py b/app/routers/dress_router.py index b0fe21d..bab651b 100644 --- a/app/routers/dress_router.py +++ b/app/routers/dress_router.py @@ -4,7 +4,7 @@ from typing import List from app.database import get_db from app.models.dress import Dress -from app.schemas.dress import DressCreate, DressUpdate, DressResponse, DressListResponse +from app.schemas.dress import DressCreate, DressUpdate, DressResponse from app.utils.response import APIResponse router = APIRouter() @@ -17,12 +17,15 @@ def create_dress(dress: DressCreate, db: Session = Depends(get_db)): db.add(db_dress) db.commit() db.refresh(db_dress) - return APIResponse.created(data=db_dress, message="服装创建成功") + return db_dress except Exception as e: db.rollback() - return APIResponse.error(message=f"服装创建失败: {str(e)}", code=500) + raise HTTPException( + status_code=500, + detail=f"服装创建失败: {str(e)}" + ) -@router.get("/", response_model=DressListResponse) +@router.get("/", response_model=List[DressResponse]) def get_all_dresses( skip: int = 0, limit: int = 100, @@ -32,28 +35,32 @@ def get_all_dresses( try: dresses = db.query(Dress).offset(skip).limit(limit).all() total = db.query(Dress).count() - return APIResponse.ok( - data={ - "items": dresses, - "total": total, - "page": skip // limit + 1 if limit > 0 else 1, - "size": limit - }, - message="服装列表获取成功" - ) + + # 构建分页数据 + result = { + "items": dresses, + "total": total, + "page": skip // limit + 1 if limit > 0 else 1, + "size": limit + } + + return result except Exception as e: - return APIResponse.error(message=f"获取服装列表失败: {str(e)}", code=500) + raise HTTPException( + status_code=500, + detail=f"获取服装列表失败: {str(e)}" + ) @router.get("/{dress_id}", response_model=DressResponse) def get_dress(dress_id: int, db: Session = Depends(get_db)): """获取单个服装记录""" - try: - dress = db.query(Dress).filter(Dress.id == dress_id).first() - if dress is None: - return APIResponse.not_found(message=f"未找到ID为{dress_id}的服装") - return APIResponse.ok(data=dress, message="服装获取成功") - except Exception as e: - return APIResponse.error(message=f"获取服装失败: {str(e)}", code=500) + dress = db.query(Dress).filter(Dress.id == dress_id).first() + if dress is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"未找到ID为{dress_id}的服装" + ) + return dress @router.put("/{dress_id}", response_model=DressResponse) def update_dress(dress_id: int, dress: DressUpdate, db: Session = Depends(get_db)): @@ -61,7 +68,10 @@ def update_dress(dress_id: int, dress: DressUpdate, db: Session = Depends(get_db try: db_dress = db.query(Dress).filter(Dress.id == dress_id).first() if db_dress is None: - return APIResponse.not_found(message=f"未找到ID为{dress_id}的服装") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"未找到ID为{dress_id}的服装" + ) # 更新服装字段 for field, value in dress.dict(exclude_unset=True).items(): @@ -69,22 +79,37 @@ def update_dress(dress_id: int, dress: DressUpdate, db: Session = Depends(get_db db.commit() db.refresh(db_dress) - return APIResponse.ok(data=db_dress, message="服装更新成功") + return db_dress + except HTTPException: + db.rollback() + raise except Exception as e: db.rollback() - return APIResponse.error(message=f"更新服装失败: {str(e)}", code=500) + raise HTTPException( + status_code=500, + detail=f"更新服装失败: {str(e)}" + ) -@router.delete("/{dress_id}") +@router.delete("/{dress_id}", status_code=status.HTTP_200_OK) def delete_dress(dress_id: int, db: Session = Depends(get_db)): """删除服装记录""" try: db_dress = db.query(Dress).filter(Dress.id == dress_id).first() if db_dress is None: - return APIResponse.not_found(message=f"未找到ID为{dress_id}的服装") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"未找到ID为{dress_id}的服装" + ) db.delete(db_dress) db.commit() - return APIResponse.ok(message="服装删除成功") + return {"message": "服装删除成功"} + except HTTPException: + db.rollback() + raise except Exception as e: db.rollback() - return APIResponse.error(message=f"删除服装失败: {str(e)}", code=500) \ No newline at end of file + raise HTTPException( + status_code=500, + detail=f"删除服装失败: {str(e)}" + ) \ No newline at end of file diff --git a/app/routers/tryon_router.py b/app/routers/tryon_router.py index b05d5aa..0165691 100644 --- a/app/routers/tryon_router.py +++ b/app/routers/tryon_router.py @@ -24,7 +24,7 @@ router = APIRouter() DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY") DASHSCOPE_API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis" -@router.post("/", response_model=TryOnResponse, status_code=201) +@router.post("", response_model=TryOnResponse, status_code=201) async def create_tryon( tryon_data: TryOnCreate, background_tasks: BackgroundTasks, @@ -63,7 +63,7 @@ async def create_tryon( person_image_url=tryon_data.person_image_url ) - return APIResponse.ok(data=db_tryon, message="试穿记录创建成功") + return db_tryon except Exception as e: logger.error(f"创建试穿记录失败: {str(e)}") db.rollback() @@ -120,7 +120,8 @@ async def get_tryons( """ try: tryons = db.query(TryOn).order_by(TryOn.id.desc()).offset(skip).limit(limit).all() - return APIResponse.ok(data=tryons, message="试穿记录列表获取成功") + + return tryons except Exception as e: logger.error(f"获取试穿记录列表失败: {str(e)}") raise HTTPException(status_code=500, detail=f"获取试穿记录列表失败: {str(e)}") @@ -139,7 +140,7 @@ async def get_tryon( tryon = db.query(TryOn).filter(TryOn.id == tryon_id).first() if not tryon: raise HTTPException(status_code=404, detail=f"未找到ID为{tryon_id}的试穿记录") - return APIResponse.ok(data=tryon, message="试穿记录获取成功") + return tryon except HTTPException: raise except Exception as e: @@ -172,7 +173,7 @@ async def update_tryon( db.commit() db.refresh(db_tryon) - return APIResponse.ok(data=db_tryon, message="试穿记录更新成功") + return db_tryon except HTTPException: raise except Exception as e: @@ -217,7 +218,7 @@ async def check_tryon_status( except Exception as e: logger.error(f"调用DashScope API检查任务状态失败: {str(e)}") - return APIResponse.ok(data=db_tryon, message="试穿任务状态检查成功") + return db_tryon except HTTPException: raise except Exception as e: diff --git a/app/schemas/dress.py b/app/schemas/dress.py index 08f2281..9922782 100644 --- a/app/schemas/dress.py +++ b/app/schemas/dress.py @@ -1,5 +1,5 @@ from pydantic import BaseModel, Field, HttpUrl -from typing import Optional, List +from typing import Optional, List, Any, Dict, Union from datetime import datetime from enum import Enum from app.models.dress import GarmentType @@ -39,18 +39,18 @@ class DressResponse(DressInDB): """服装API响应模型""" pass -class DressListResponse(BaseModel): - items: List[DressResponse] +class PaginatedResponse(BaseModel): + """通用分页响应""" + items: List[Any] total: int page: int size: int - + class Config: orm_mode = True class StandardResponse(BaseModel): """标准API响应格式""" - success: bool = True code: int = 200 message: str = "操作成功" - data: Optional[dict] = None \ No newline at end of file + data: Optional[Any] = None \ No newline at end of file diff --git a/app/utils/response.py b/app/utils/response.py index 42514ae..e47df54 100644 --- a/app/utils/response.py +++ b/app/utils/response.py @@ -1,57 +1,56 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Union, ClassVar from fastapi import status from fastapi.responses import JSONResponse +import os + +from app.models.api_response import APIResponseModel class APIResponse: """API标准响应格式工具类""" - @staticmethod - def success( - data: Any = None, - message: str = "操作成功", - code: int = 200 - ) -> Dict[str, Any]: - """ - 成功响应 - - Args: - data: 响应数据 - message: 响应消息 - code: 状态码 - - Returns: - 标准响应格式的字典 - """ - return { - "success": True, - "code": code, - "message": message, - "data": data - } + # 全局开关,控制是否使用标准响应格式 + USE_STANDARD_RESPONSE = os.environ.get("USE_STANDARD_RESPONSE", "1") == "1" @staticmethod - def error( - message: str = "操作失败", - code: int = 400, - data: Any = None - ) -> Dict[str, Any]: - """ - 错误响应 + def ok(data: Any = None, message: str = "操作成功") -> Dict[str, Any]: + """成功响应""" + if not APIResponse.USE_STANDARD_RESPONSE: + return data - Args: - message: 错误消息 - code: 错误状态码 - data: 附加错误数据 - - Returns: - 标准响应格式的字典 + return APIResponseModel( + code=200, + message=message, + data=data + ).dict() + + @staticmethod + def error(message: str = "操作失败", code: int = 400, data: Any = None) -> Dict[str, Any]: + """错误响应""" + # 错误响应即使禁用了标准格式也返回标准格式,确保错误信息清晰 + return APIResponseModel( + code=code, + message=message, + data=data + ).dict() + + @staticmethod + def format_response(data: Any, message: str = "操作成功", code: int = 200) -> Dict: """ - return { - "success": False, - "code": code, - "message": message, - "data": data + 根据环境变量决定是否返回标准格式的响应 + + 如果USE_STANDARD_RESPONSE=1,返回标准格式: + { + "code": 200, + "message": "操作成功", + "data": {...} } + + 如果USE_STANDARD_RESPONSE=0,直接返回data + """ + if APIResponse.USE_STANDARD_RESPONSE: + return APIResponseModel(code=code, message=message, data=data).dict() + else: + return data if data is not None else {"message": message} @staticmethod def json_response( @@ -76,12 +75,18 @@ class APIResponse: Returns: JSONResponse对象 """ - content = { - "success": success, - "code": code, - "message": message, - "data": data - } + if not APIResponse.USE_STANDARD_RESPONSE and success: + return JSONResponse( + content=data, + status_code=status_code, + headers=headers + ) + + content = APIResponseModel( + code=code, + message=message, + data=data + ).dict() return JSONResponse( content=content, @@ -90,25 +95,26 @@ class APIResponse: ) # 常用响应码封装 - @classmethod - def ok(cls, data: Any = None, message: str = "操作成功") -> Dict[str, Any]: - """200 成功""" - return cls.success(data, message, 200) - @classmethod def created(cls, data: Any = None, message: str = "创建成功") -> Dict[str, Any]: """201 创建成功""" - return cls.success(data, message, 201) + if not cls.USE_STANDARD_RESPONSE: + return data + return cls.ok(data, message) @classmethod def accepted(cls, data: Any = None, message: str = "请求已接受") -> Dict[str, Any]: """202 已接受""" - return cls.success(data, message, 202) + if not cls.USE_STANDARD_RESPONSE: + return data + return cls.ok(data, message) @classmethod def no_content(cls) -> Dict[str, Any]: """204 无内容""" - return cls.success(None, "无内容", 204) + if not cls.USE_STANDARD_RESPONSE: + return None + return cls.ok(None, "无内容") @classmethod def bad_request(cls, message: str = "请求参数错误") -> Dict[str, Any]: