FastAPI 實戰(zhàn)技巧:統(tǒng)一響應格式 + 全局異常處理,一次搞定!
在開發(fā) FastAPI 項目的過程中,你是否遇到過這些問題?
- 每個接口的返回結構不統(tǒng)一,前端不好處理?
- 拋出異常時直接報 500,連自己都看不懂?
- 想統(tǒng)一日志、錯誤、結構處理,結果寫得四分五裂?
這篇文章帶你一步步落地:統(tǒng)一響應結構 + 全局異常處理機制,讓接口更規(guī)范、更易維護!
1. 為什么要統(tǒng)一響應格式?
統(tǒng)一返回格式的好處:
- 前端開發(fā)更容易解析數據結構
- 后期維護更省心,不用滿項目找問題
- 可擴展性強,適配多種客戶端需求
推薦標準格式如下:
{
"code":0,
"message":"OK",
"data":{
"id":1,
"name":"Alice"
}
}
字段解釋:
字段名 | 類型 | 說明 |
code | int | 自定義業(yè)務狀態(tài)碼 |
message | str | 提示信息 |
data | object | 實際返回的業(yè)務數據,支持對象/數組/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)
接口文檔中將展示完整的結構,同時前端調用也能穩(wěn)定解析。
3. 全局異常處理
FastAPI 默認錯誤返回 HTTP 500 和系統(tǒng) Traceback,不適合直接暴露給客戶端。
我們可以自定義異常類 + 注冊全局處理器。
(1) 自定義業(yè)務異常
class BusinessException(Exception):
def __init__(self, code: int = 4001, message: str = "業(yè)務異常"):
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": "系統(tǒng)異常",
"data": None
}
)
調用:
register_exceptions(app)
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 = "業(yè)務異常"):
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": "系統(tǒng)錯誤", "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. 總結
- 統(tǒng)一響應結構 提高接口一致性,利于前后端協(xié)作
- 異常統(tǒng)一處理 避免信息泄露、增強健壯性
- 泛型封裝響應模型,優(yōu)雅又實用!