點擊python編程從入門到實踐,置頂 公衆號重磅 python入門資料,第一時間送達前端
讀完須要10分鐘python
速讀僅需 4 分鐘數據庫
/ python 生產實戰 python 大型項目神器實戰 /編程
在 fastapi 中有一個強大而且簡單易懂的系統:依賴注入系統api
1緩存
什麼是依賴注入安全
依賴注入首先意味着在程序中咱們的代碼能夠聲明一些它必須依賴的項:咱們稱之爲 dependencies,也就是依賴項。而後,在實際運行中,fastapi 會把全部須要的依賴項提供給你的代碼,稱之爲注入依賴項。微信
一句話簡單解釋:本來接受各類參數來構造一個對象,如今只接受一個參數這個參數是已經實例化的對象,對象的『依賴』是注入進來的,而和它的構造方式解耦了。構造它這個『控制』操做也交給了第三方。cookie
1.1閉包
依賴注入適用場景列舉:
1.業務邏輯複用
2.共享數據庫鏈接
3.安全機制、權限校驗、角色管理等
全部上述使用場景,藉助於依賴注入可提升代碼複用率,減小代碼重複。
2
依賴注入實現方案
在看具體的實現依賴注入以前咱們先從流程上來理解一下整個數據流轉。當一個新的請求到來的時候,實際的調用流程以下:
1.調用依賴項函數(傳遞合適的參數)
2.獲得依賴項目函數的返回結果
3.把返回結果傳遞給路由函數中對應的參數
4.路由函數中業務流數據處理
5.獲取的數據返回給客戶端/前端
2.1
函數級依賴項
# -*- encoding: utf-8 -*-from fastapi import Depends, FastAPIapp = FastAPI()async def common_paras(request_source: str = None, page: int = 0, limit: int = 100): return {"request_source": request_source, "page": page, "limit": limit}@app.get("/items/info")async def read_items_info(commons: dict = Depends(common_paras)): return commons@app.get("/users/info")async def read_users_info(commons: dict = Depends(common_paras)): return commons
2.2
類級依賴項
# -*- encoding: utf-8 -*-from fastapi import Depends, FastAPIapp = FastAPI()fake_items_db = [{"user_name": "HaiShiNiu"}, {"user_name": "WangXiaoXiao"}, {"user_name": "ZhongCen"}]class CommonQueryParams: def __init__(self, request_source: str = None, page: int = 0, limit: int = 100): self.request_source = request_source self.page = page self.limit = limit@app.get("/items/info")async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): response = {} if commons.request_source: response.update({"q": commons.q}) items = fake_items_db[commons.page : commons.page + commons.limit] response.update({"items": items}) return response
2.3
遞歸依賴項
# -*- encoding: utf-8 -*-from fastapi import Cookie, Depends, FastAPIapp = FastAPI()def query_extractor(q11: str, q12: str): return q11 + q12def query_or_cookie_extractor(q2: str = Depends(query_extractor), last_query: str = Cookie(None)): if not q2: return last_query return q2@app.get("/items/")async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):return {"q_or_cookie": query_or_default}
注意:有些場景是須要對依賴項的屢次調用的狀況。
若是某個依賴項在同一個路徑操做中被聲明瞭屢次,例如,多個依賴項都有一個共同的子依賴項,那麼 fastapi 默認在每一次請求中只會調用這個依賴項一次。fastapi 會把這個依賴項的返回值緩存起來,而後把這個值傳遞給須要的依賴項,而不是在同一個請求中屢次調用這個依賴項。在有些場景下,咱們並不須要緩存這個依賴項的返回值,而是須要屢次調用,那麼咱們可使用參數 use_cache=False 來禁止依賴項的緩存。
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): return {"fresh_value": fresh_value}
2.4
基於路徑操做裝飾器依賴項
在有些狀況下,咱們並不須要依賴項的返回值,但仍然須要依賴項被執行。在這種狀況下,咱們能夠經過路徑操做裝飾器來操做依賴項的一個列表。路徑操做裝飾器接收一個可選的參數 dependencies,參數內容是 Depends()列表。
# -*- encoding: utf-8 -*-from fastapi import Depends, FastAPI, Header, HTTPExceptionapp = FastAPI()async def verify_token(x_token: str = Header(...)): if x_token != "token": raise HTTPException(status_code=400, detail="X-Token header invalid")async def verify_key(x_key: str = Header(...)): if x_key != "key": raise HTTPException(status_code=400, detail="X-Key header invalid") return x_key@app.get("/items/info", dependencies=[Depends(verify_token), Depends(verify_key)])async def read_items_info(): return [{"function_name": "Foo"}, {"function_name": "Bar"}]
這些依賴項與普通依賴項的執行相同,但他們的返回值(若是有)不會被傳遞給路徑操做函數。咱們能夠重複使用已經聲明的依賴項,不管他們是否有返回值,都不會影響依賴項的執行。
2.5
帶有 yield 功能依賴項
fastapi 支持依賴項在請求結束後作一些額外的工做。要實現這個功能,咱們須要用 yield 代替 return,而後其後添加一些額外的工做。咱們舉個例子:建立一個數據庫連接,而後在請求結束後關閉這個連接。固然處理這個 case 的解決方案也是有不少的,本次咱們就基於使用 yield 功能的依賴項進行實現
# -*- encoding: utf-8 -*-async def get_db_info(): """ 獲取數據庫鏈接信息 """ # 建立連接 db = DBSession() try: yield db # 數據庫使用 finally: db.close() # 關閉數據庫連接
簡單說明一下:yield db 後面的值 db 會注入給路徑操做或者其餘依賴項。yield db 後面的代碼在 response 提交以後纔會執行。使用 try 語句來捕獲可能發生的異常。爲了確保不管是否有異常發生都能執行退出邏輯,咱們這裏在 finally 語句中執行退出邏輯。可是要注意,若是嘗試在 yield 後面拋出 HTTPException,不會起到任何做用。yield 以後的退出代碼是在異常處理器以後被執行的,所以沒法捕捉異常的發生。
2.6
可參數化依賴項
咱們前面使用的依賴項都是固定的函數或者類,但有時想在依賴項中設置不一樣的參數,同時又不用聲明不一樣的函數或類。此時可利用一個可調用的類實例來實現這個功能。注意:類自己就是可調用的,而它的實例須要實現一個特定類方法纔是可調用的:call
一句話介紹 call:call 是 Python 的一個黑魔法方法,核心功能是經過對象實例能夠直接觸發 call 中的邏輯,在 Tornado 源碼中這種用法不少,有興趣的同窗能夠看看我在公衆號中的關於 Tornado 的專欄文章。
# -*- encoding: utf-8 -*-from fastapi import Depends, FastAPIapp = FastAPI()class FixedContentQueryCheck(object): def __init__(self, fixed_content: str): self.fixed_content = fixed_content def __call__(self, q: str = ""): if q: return self.fixed_content in q return Falsechecker = FixedContentQueryCheck("bar")@app.get("/query-checker/")async def read_query_check(fixed_content_included: bool = Depends(checker)): return {"fixed_content_in_query": fixed_content_included}
3
總結
1.簡單介紹了一下什麼是依賴注入以及使用場景
2.咱們系統的梳理了實現依賴注入的各類方式供你們在生產環境中進行使用
原創不易,只願能幫助那些須要這些內容的同行或剛入行的小夥伴,你的每次 點贊、分享 都是我繼續創做下去的動力,我但願能在推廣 python 技術的道路上盡我一份力量,歡迎在評論區向我提問,我都會一一解答,記得一鍵三連支持一下哦!
加入python學習交流微信羣,請後臺回覆「入羣」
往期推薦
大型fastapi項目實戰 靠 python 中間件解決方案漲薪了
大型fastapi項目實戰 高併發請求神器之aiohttp(下)
大型fastapi項目實戰 高併發請求神器之aiohttp(上) [建議收藏]
本文分享自微信公衆號 - python編程軍火庫(PythonCoder1024)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。