在深入研究依賴注入系統(tǒng)之前,讓我們升級(jí)前面的例子。
在前面的示例中,我們dict從我們的依賴項(xiàng)(“可靠”)中返回 a :
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
但是隨后我們?cè)诼窂讲僮骱瘮?shù)dict的參數(shù)commons中得到了一個(gè)。
而且我們知道編輯器不能為dicts提供很多支持(比如補(bǔ)全),因?yàn)樗麄儫o(wú)法知道它們的鍵和值類型。
我們可以做得更好...
到目前為止,您已經(jīng)看到了聲明為函數(shù)的依賴項(xiàng)。
但這不是聲明依賴項(xiàng)的唯一方法(盡管它可能更常見(jiàn))。
關(guān)鍵因素是依賴項(xiàng)應(yīng)該是“可調(diào)用的”。
Python 中的“可調(diào)用”是 Python 可以像函數(shù)一樣“調(diào)用”的任何東西。
因此,如果您有一個(gè)對(duì)象something(可能不是函數(shù))并且您可以“調(diào)用”它(執(zhí)行它),例如:
something()
或者
something(some_argument, some_keyword_argument="foo")
那么它是一個(gè)“可調(diào)用的”。
您可能會(huì)注意到,要?jiǎng)?chuàng)建 Python 類的實(shí)例,您使用相同的語(yǔ)法。
例如:
class Cat:
def __init__(self, name: str):
self.name = name
fluffy = Cat(name="Mr Fluffy")
在這種情況下,fluffy是類的一個(gè)實(shí)例Cat。
而要?jiǎng)?chuàng)造fluffy,你就是在“呼喚” Cat。
因此,Python 類也是一個(gè)可調(diào)用的.
然后,在FastAPI 中,您可以使用 Python 類作為依賴項(xiàng)。
FastAPI 實(shí)際檢查的是它是“可調(diào)用的”(函數(shù)、類或其他任何東西)和定義的參數(shù)。
如果在FastAPI 中傳遞“可調(diào)用”作為依賴項(xiàng),它將分析該“可調(diào)用”的參數(shù),并以與路徑操作函數(shù)的參數(shù)相同的方式處理它們。包括子依賴。
這也適用于根本沒(méi)有參數(shù)的可調(diào)用對(duì)象。與沒(méi)有參數(shù)的路徑操作函數(shù)相同。
然后,我們可以將依賴項(xiàng)“可靠”common_parameters從上面更改為類CommonQueryParams:
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
注意__init__用于創(chuàng)建類的實(shí)例的方法:
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
...它具有與我們之前相同的參數(shù)common_parameters:
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
這些參數(shù)是FastAPI將用來(lái)“解決”依賴關(guān)系的。
在這兩種情況下,它將具有:
在這兩種情況下,數(shù)據(jù)都將被轉(zhuǎn)換、驗(yàn)證、記錄在 OpenAPI 模式等上。
現(xiàn)在您可以使用此類聲明您的依賴項(xiàng)。
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
FastAPI調(diào)用CommonQueryParams該類。這將創(chuàng)建該類的“實(shí)例”,并且該實(shí)例將作為參數(shù)傳遞commons給您的函數(shù)。
注意我們CommonQueryParams在上面的代碼中是如何寫(xiě)兩次的:
commons: CommonQueryParams = Depends(CommonQueryParams)
最后CommonQueryParams,在:
... = Depends(CommonQueryParams)
...是FastAPI實(shí)際用來(lái)知道什么是依賴項(xiàng)的。
FastAPI 將從中提取聲明的參數(shù),這就是 FastAPI 將實(shí)際調(diào)用的內(nèi)容。
在這種情況下,第一個(gè)CommonQueryParams, 在:
commons: CommonQueryParams ...
...對(duì)FastAPI沒(méi)有任何特殊含義。FastAPI 不會(huì)將它用于數(shù)據(jù)轉(zhuǎn)換、驗(yàn)證等(因?yàn)樗? Depends(CommonQueryParams)為此使用 )。
你實(shí)際上可以只寫(xiě):
commons = Depends(CommonQueryParams)
..如:
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons=Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
但是鼓勵(lì)聲明類型,因?yàn)檫@樣您的編輯器將知道將作為參數(shù)傳遞的內(nèi)容commons,然后它可以幫助您完成代碼完成、類型檢查等:
但是你看到我們這里有一些代碼重復(fù),寫(xiě)了CommonQueryParams兩次:
commons: CommonQueryParams = Depends(CommonQueryParams)
FastAPI為這些情況提供了一種快捷方式,在這種情況下,依賴項(xiàng)特別是一個(gè)類,F(xiàn)astAPI將“調(diào)用”以創(chuàng)建類本身的實(shí)例。
對(duì)于這些特定情況,您可以執(zhí)行以下操作:
而不是寫(xiě):
commons: CommonQueryParams = Depends(CommonQueryParams)
...你寫(xiě):
commons: CommonQueryParams = Depends()
你聲明依賴作為參數(shù)的類型,并使用Depends()其“默認(rèn)”值(即后=),該函數(shù)的參數(shù),在沒(méi)有任何參數(shù)Depends(),而不必編寫(xiě)完整的類再次里面的Depends(CommonQueryParams)。
同樣的例子看起來(lái)像:
from typing import Optional
from fastapi import Depends, FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends()):
response = {}
if commons.q:
response.update({"q": commons.q})
items = fake_items_db[commons.skip : commons.skip + commons.limit]
response.update({"items": items})
return response
...而FastAPI會(huì)知道該怎么做。
提示
如果這看起來(lái)更令人困惑而不是有用,請(qǐng)忽略它,您不需要它。
這只是一個(gè)捷徑。因?yàn)镕astAPI關(guān)心幫助您最大程度地減少代碼重復(fù)。
更多建議: