1. 为什么要统一响应格式?
统一返回格式的好处:
- 前端开发更容易解析数据结构
- 后期维护更省心,不用满项目找问题
- 可扩展性强,适配多种客户端需求
推荐标准格式如下:
{
"code":0,
"message":"OK",
"data":{
"id":1,
"name":"Alice"
}
}
字段解释:
字段名 | 类型 | 说明 |
---|---|---|
code | int | 自定义业务状态码 |
message | str | 提示信息 |
data | object | 实际返回的业务数据,支持对象/数组/null |
2. 响应模型封装
定义通用响应模型(支持泛型):
from pydantic.generics import GenericModel
from typing import Generic, TypeVar, Optional
T = TypeVar("T")
class Response(GenericModel, Generic[T]):
code: int = 0
message: str = "OK"
data: Optional[T] = None
这种结构支持响应任何类型的数据,只需:
@app.get("/user/{user_id}", response_model=Response[UserOut])
async def get_user(user_id: int):
user = await User.get(id=user_id)
return Response(data=user)
接口文档中将展示完整的结构,同时前端调用也能稳定解析。
3. 全局异常处理
FastAPI 默认错误返回 HTTP 500 和系统 Traceback,不适合直接暴露给客户端。
我们可以自定义异常类 + 注册全局处理器。
(1) 自定义业务异常
class BusinessException(Exception):
def __init__(self, code: int = 4001, message: str = "业务异常"):
self.code = code
self.message = message
(2) 注册异常处理器
from fastapi.responses import JSONResponse
from fastapi import Request, FastAPI
defregister_exceptions(app: FastAPI):
@app.exception_handler(BusinessException)
asyncdefbusiness_exception_handler(request: Request, exc: BusinessException):
return JSONResponse(
status_code=200,
content={
"code": exc.code,
"message": exc.message,
"data": None
}
)
@app.exception_handler(Exception)
asyncdefgeneral_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={
"code": 5000,
"message": "系统异常",
"data": None
}
)
调用:
register_exceptions(app)
1.
4. 异常使用示例
@app.get("/users/{user_id}", response_model=Response[UserOut])
async def get_user(user_id: int):
user = await User.get_or_none(id=user_id)
if not user:
raise BusinessException(code=4040, message="用户不存在")
return Response(data=user)
5. 项目推荐结构
app/
├── main.py # 启动入口
├── api/
│ └── user.py # 路由模块
├── core/
│ ├── response.py # 响应模型
│ ├── exception.py # 异常类与注册器
(1) response.py
from pydantic.generics import GenericModel
from typing import Generic, TypeVar, Optional
T = TypeVar("T")
class Response(GenericModel, Generic[T]):
code: int = 0
message: str = "OK"
data: Optional[T] = None
(2) exception.py
from fastapi import Request, FastAPI
from fastapi.responses import JSONResponse
classBusinessException(Exception):
def__init__(self, code: int = 4001, message: str = "业务异常"):
self.code = code
self.message = message
defregister_exceptions(app: FastAPI):
@app.exception_handler(BusinessException)
asyncdefbusiness_handler(request: Request, exc: BusinessException):
return JSONResponse(
status_code=200,
content={"code": exc.code, "message": exc.message, "data": None}
)
@app.exception_handler(Exception)
asyncdefglobal_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"code": 5000, "message": "系统错误", "data": None}
)
(3) main.py
from fastapi import FastAPI
from app.core.exception import register_exceptions
from app.api import user
app = FastAPI()
register_exceptions(app)
app.include_router(user.router)
6. 总结
- 统一响应结构 提高接口一致性,利于前后端协作
- 异常统一处理 避免信息泄露、增强健壮性
- 泛型封装响应模型,优雅又实用!