FastAPI教程 作為依賴的類

2021-11-02 17:04 更新

在深入研究依賴注入系統(tǒng)之前,讓我們升級(jí)前面的例子。

來(lái)自上一個(gè)示例的一個(gè)字典

在前面的示例中,我們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)系的。

在這兩種情況下,它將具有:

  • 一個(gè)可選的q查詢參數(shù)是str.
  • 一個(gè)skip查詢參數(shù)是int,用的默認(rèn)0。
  • 一個(gè)limit查詢參數(shù)是int,用的默認(rèn)100。

在這兩種情況下,數(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ù)。

類型注釋與 Depends

注意我們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ù)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)