FastAPI 的依賴注入
- FastAPI 有一個非常強大但直觀的依賴注入系統
- 它被設計為非常易於使用,並且使任何開發人員都可以非常輕松地將其他組件與 FastAPI 集成
什么是依賴注入
- 在編程中,為保證代碼成功運行,先導入或聲明其所需要的【依賴】,如子函數、數據庫連接等等
- 將依賴項的返回值注入到特定參數中
依賴注入有什么作用
- 業務邏輯復用的場景使用,可以減少重復代碼
- 共享數據庫連接
- 強制執行安全性、身份驗證、角色管理等
- 其他使用場景
FastAPI 的兼容性
依賴注入系統的簡單性使得 FastAPI 兼容:
- 所有的關系型數據庫
- NoSQL 數據庫
- 第三方的包和 API
- 認證、授權系統
- 響應數據注入系統
依賴注入的簡單栗子
第一步:創建依賴項
from typing import Optional # 1、編寫依賴項 async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit}
- 它就是一個普通函數,只不過加了 async 異步關鍵字
- 函數參數有三個,都是可選的
- 依賴項可以返回任意內容,這里的返回值是一個 dict,把傳進來的值塞進 dict,再進行返回
第二步:導入 Depends
from typing import Optional # 2、導入 Depends from fastapi import Depends # 1、編寫依賴項函數 async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit}
第三步:聲明 Depends,完成依賴注入
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠蘿測試筆記 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/9/24 1:08 下午 # file: 25_dependency.py """ from typing import Optional, Dict, Any # 2、導入 Depends from fastapi import Depends, FastAPI import uvicorn app = FastAPI() # 1、編寫依賴項函數 async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit} # 3、編寫路徑操作函數,參數聲明為 Depends @app.get("/items") async def read_items(commons: Dict[str, Any] = Depends(common_parameters)): return commons if __name__ == "__main__": uvicorn.run(app="25_dependency:app", host="127.0.0.1", port=8080, reload=True, debug=True)
- commons 參數聲明了 Depends() ,和 Body()、Query() 的使用方式一樣
- 注意:填寫依賴項的時候不需要加 (),只寫函數名就行Depends(common_parameters) ,且填寫的依賴項必須是一個函數
當請求 /items 時,FastAPI 會做哪些事?
- 通過正確的參數調用依賴項函數 common_parameters
- 從依賴項函數中獲取 return 值
- 將返回值賦值給路徑操作函數中的參數 commons
- 執行完依賴項函數后,才會執行路徑操作函數
解析 commons: Dict[str, Any] = Depends(common_parameters)
- 雖然 commons 參數類型聲明為 Dict,但請求 /items 的時候並不是通過 Request Body 來傳參的
- 因為 commons 參數接收的是依賴項函數 common_parameters 的返回值,所以這個 Dict 是限制了依賴項函數的返回值類型,並不是請求數據類型
- /items 的請求傳參方式是查詢參數
正確傳參的請求結果
直接在 Swagger API 文檔上測試了,順便看看長啥樣
- 從文檔中也可以看到,/items 要傳三個查詢參數,其實就是依賴項函數的參數
- FastAPI 會將所有依賴項信息添加到 OpenAPI Schema 中,以便在 Swagger API 中顯示(如上圖)
請求數據驗證失敗的請求結果
即使是依賴項,FastAPI 也會對它做數據驗證,不符合類型則報錯
async 或 not async
- 可以在非 async 路徑操作函數中使用 async 的依賴項
- 也可以在 async 路徑操作函數中使用非 async 的依賴項
- FastAPI 知道要怎么處理
# 非 async 依賴項 def test_dep(name: str): return name # async 路徑操作函數 @app.get("/name") async def test_name(name: str = Depends(test_dep)): return name # async 依賴項 async def test_user_info(info: dict): return info # 非 async 路徑操作函數 @app.get("/info") def test_info(info: dict = Depends(test_user_info)): return info
依賴項函數參數類型是一個字典
from typing import Optional, Dict, Any # 2、導入 Depends from fastapi import Depends, FastAPI import uvicorn app = FastAPI() # 1、編寫依賴項 async def common_parameters(*, q: Optional[str] = None, skip: int = 0, limit: int = 100, # 新增一個 Dict 類型的參數 info: Dict[str, Any]): return {"q": q, "skip": skip, "limit": limit, "info": info} # 3、編寫路徑操作函數,參數聲明為 Depends @app.get("/items") async def read_items(commons: Dict[str, Any] = Depends(common_parameters)): return commons if __name__ == "__main__": uvicorn.run(app="25_dependency:app", host="127.0.0.1", port=8080, reload=True, debug=True)
查看 Swagger API 文檔
正確傳參的請求結果