FastAPI教程 作為依賴的類

2021-11-02 17:04 更新

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

來自上一個示例的一個字典

在前面的示例中,我們dict從我們的依賴項(“可靠”)中返回 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

但是隨后我們在路徑操作函數(shù)dict的參數(shù)commons中得到了一個。

而且我們知道編輯器不能為dicts提供很多支持(比如補全),因為他們無法知道它們的鍵和值類型。

我們可以做得更好...

什么使依賴

到目前為止,您已經(jīng)看到了聲明為函數(shù)的依賴項。

但這不是聲明依賴項的唯一方法(盡管它可能更常見)。

關鍵因素是依賴項應該是“可調(diào)用的”。

Python 中的“可調(diào)用”是 Python 可以像函數(shù)一樣“調(diào)用”的任何東西。

因此,如果您有一個對象something(可能不是函數(shù))并且您可以“調(diào)用”它(執(zhí)行它),例如:

something()

或者

something(some_argument, some_keyword_argument="foo")

那么它是一個“可調(diào)用的”。

類作為依賴

您可能會注意到,要創(chuàng)建 Python 類的實例,您使用相同的語法。

例如:

class Cat:
    def __init__(self, name: str):
        self.name = name


fluffy = Cat(name="Mr Fluffy")

在這種情況下,fluffy是類的一個實例Cat。

而要創(chuàng)造fluffy,你就是在“呼喚” Cat。

因此,Python 類也是一個可調(diào)用的.

然后,在FastAPI 中,您可以使用 Python 類作為依賴項。

FastAPI 實際檢查的是它是“可調(diào)用的”(函數(shù)、類或其他任何東西)和定義的參數(shù)。

如果在FastAPI 中傳遞“可調(diào)用”作為依賴項,它將分析該“可調(diào)用”的參數(shù),并以與路徑操作函數(shù)的參數(shù)相同的方式處理它們。包括子依賴。

這也適用于根本沒有參數(shù)的可調(diào)用對象。與沒有參數(shù)的路徑操作函數(shù)相同。

然后,我們可以將依賴項“可靠”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)建類的實例的方法:

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將用來“解決”依賴關系的。

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

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

在這兩種情況下,數(shù)據(jù)都將被轉(zhuǎn)換、驗證、記錄在 OpenAPI 模式等上。

怎么使用

現(xiàn)在您可以使用此類聲明您的依賴項。

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ù)傳遞commons給您的函數(shù)。

類型注釋與 Depends

注意我們CommonQueryParams在上面的代碼中是如何寫兩次的:

commons: CommonQueryParams = Depends(CommonQueryParams)

最后CommonQueryParams,在:

... = Depends(CommonQueryParams)

...是FastAPI實際用來知道什么是依賴項的。

FastAPI 將從中提取聲明的參數(shù),這就是 FastAPI 將實際調(diào)用的內(nèi)容。

在這種情況下,第一個CommonQueryParams, 在:

commons: CommonQueryParams ...

...對FastAPI沒有任何特殊含義。FastAPI 不會將它用于數(shù)據(jù)轉(zhuǎn)換、驗證等(因為它正在= Depends(CommonQueryParams)為此使用 )。

你實際上可以只寫:

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

但是鼓勵聲明類型,因為這樣您的編輯器將知道將作為參數(shù)傳遞的內(nèi)容commons,然后它可以幫助您完成代碼完成、類型檢查等:

捷徑

但是你看到我們這里有一些代碼重復,寫了CommonQueryParams兩次:

commons: CommonQueryParams = Depends(CommonQueryParams)

FastAPI為這些情況提供了一種快捷方式,在這種情況下,依賴項特別是一個類,F(xiàn)astAPI將“調(diào)用”以創(chuàng)建類本身的實例。

對于這些特定情況,您可以執(zhí)行以下操作:

而不是寫:

commons: CommonQueryParams = Depends(CommonQueryParams)

...你寫:

commons: CommonQueryParams = Depends()

你聲明依賴作為參數(shù)的類型,并使用Depends()其“默認”值(即后=),該函數(shù)的參數(shù),在沒有任何參數(shù)Depends(),而不必編寫完整的類再次里面的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: 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會知道該怎么做。

提示

如果這看起來更令人困惑而不是有用,請忽略它,您不需要它。

這只是一個捷徑。因為FastAPI關心幫助您最大程度地減少代碼重復。


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號