FastAPI 实战技巧:统一响应格式 + 全局异常处理

0 阅读2分钟

1. 为什么要统一响应格式?

统一返回格式的好处:

  • 前端开发更容易解析数据结构
  • 后期维护更省心,不用满项目找问题
  • 可扩展性强,适配多种客户端需求

推荐标准格式如下:

{
  "code":0,
"message":"OK",
"data":{
    "id":1,
    "name":"Alice"
}
}

字段解释:

字段名类型说明
codeint自定义业务状态码
messagestr提示信息
dataobject实际返回的业务数据,支持对象/数组/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. 总结

  • 统一响应结构 提高接口一致性,利于前后端协作
  • 异常统一处理 避免信息泄露、增强健壮性
  • 泛型封装响应模型,优雅又实用!