您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)python fastapi中依賴注入系統(tǒng)的工作原理以及使用方法,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
在 fastapi 中有一個強大并且簡單易懂的系統(tǒng):依賴注入系統(tǒng)
1
什么是依賴注入
依賴注入首先意味著在程序中我們的代碼可以聲明一些它必須依賴的項:我們稱之為 dependencies,也就是依賴項。然后,在實際運行中,fastapi 會把所有需要的依賴項提供給你的代碼,稱之為注入依賴項。
一句話簡單解釋:原本接受各種參數(shù)來構(gòu)造一個對象,現(xiàn)在只接受一個參數(shù)這個參數(shù)是已經(jīng)實例化的對象,對象的『依賴』是注入進來的,而和它的構(gòu)造方式解耦了。構(gòu)造它這個『控制』操作也交給了第三方。
1.1
依賴注入適用場景列舉:
1.業(yè)務(wù)邏輯復(fù)用
2.共享數(shù)據(jù)庫連接
3.安全機制、權(quán)限校驗、角色管理等
所有上述使用場景,借助于依賴注入可提高代碼復(fù)用率,減少代碼重復(fù)。
2
依賴注入實現(xiàn)方案
在看具體的實現(xiàn)依賴注入之前我們先從流程上來理解一下整個數(shù)據(jù)流轉(zhuǎn)。當一個新的請求到來的時候,實際的調(diào)用流程如下:
1.調(diào)用依賴項函數(shù)(傳遞合適的參數(shù))
2.得到依賴項目函數(shù)的返回結(jié)果
3.把返回結(jié)果傳遞給路由函數(shù)中對應(yīng)的參數(shù)
4.路由函數(shù)中業(yè)務(wù)流數(shù)據(jù)處理
5.獲取的數(shù)據(jù)返回給客戶端/前端
2.1
函數(shù)級依賴項
# -*- 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}
注意:有些場景是需要對依賴項的多次調(diào)用的情況。
如果某個依賴項在同一個路徑操作中被聲明了多次,例如,多個依賴項都有一個共同的子依賴項,那么 fastapi 默認在每一次請求中只會調(diào)用這個依賴項一次。fastapi 會把這個依賴項的返回值緩存起來,然后把這個值傳遞給需要的依賴項,而不是在同一個請求中多次調(diào)用這個依賴項。在有些場景下,我們并不需要緩存這個依賴項的返回值,而是需要多次調(diào)用,那么我們可以使用參數(shù) use_cache=False 來禁止依賴項的緩存。
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): return {"fresh_value": fresh_value}
2.4
基于路徑操作裝飾器依賴項
在有些情況下,我們并不需要依賴項的返回值,但仍然需要依賴項被執(zhí)行。在這種情況下,我們可以通過路徑操作裝飾器來操作依賴項的一個列表。路徑操作裝飾器接收一個可選的參數(shù) dependencies,參數(shù)內(nèi)容是 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"}]
這些依賴項與普通依賴項的執(zhí)行相同,但他們的返回值(如果有)不會被傳遞給路徑操作函數(shù)。我們可以重復(fù)使用已經(jīng)聲明的依賴項,無論他們是否有返回值,都不會影響依賴項的執(zhí)行。
2.5
帶有 yield 功能依賴項
fastapi 支持依賴項在請求結(jié)束后做一些額外的工作。要實現(xiàn)這個功能,我們需要用 yield 代替 return,然后其后添加一些額外的工作。我們舉個例子:創(chuàng)建一個數(shù)據(jù)庫鏈接,然后在請求結(jié)束后關(guān)閉這個鏈接。當然處理這個 case 的解決方案也是有很多的,本次我們就基于使用 yield 功能的依賴項進行實現(xiàn)
# -*- encoding: utf-8 -*-async def get_db_info(): """ 獲取數(shù)據(jù)庫連接信息 """ # 創(chuàng)建鏈接 db = DBSession() try: yield db # 數(shù)據(jù)庫使用 finally: db.close() # 關(guān)閉數(shù)據(jù)庫鏈接
簡單說明一下:yield db 后面的值 db 會注入給路徑操作或者其他依賴項。yield db 后面的代碼在 response 提交之后才會執(zhí)行。使用 try 語句來捕獲可能發(fā)生的異常。為了確保無論是否有異常發(fā)生都能執(zhí)行退出邏輯,我們這里在 finally 語句中執(zhí)行退出邏輯。但是要注意,如果嘗試在 yield 后面拋出 HTTPException,不會起到任何作用。yield 之后的退出代碼是在異常處理器之后被執(zhí)行的,因此無法捕捉異常的發(fā)生。
2.6
可參數(shù)化依賴項
我們前面使用的依賴項都是固定的函數(shù)或者類,但有時想在依賴項中設(shè)置不同的參數(shù),同時又不用聲明不同的函數(shù)或類。此時可利用一個可調(diào)用的類實例來實現(xiàn)這個功能。注意:類本身就是可調(diào)用的,而它的實例需要實現(xiàn)一個特定類方法才是可調(diào)用的:call
一句話介紹 call:call 是 Python 的一個黑魔法方法,核心功能是通過對象實例可以直接觸發(fā) call 中的邏輯,在 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}
我們系統(tǒng)的梳理了實現(xiàn)依賴注入的各種方式供大家在生產(chǎn)環(huán)境中進行使用
看完上述內(nèi)容,你們對python fastapi中依賴注入系統(tǒng)的工作原理以及使用方法有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。