FastAPI教程 請(qǐng)求體 - 多個(gè)參數(shù)

2022-08-20 11:34 更新

既然我們已經(jīng)知道了如何使用 Path 和 Query,下面讓我們來(lái)了解一下請(qǐng)求體聲明的更高級(jí)用法。

混合使用 Path、Query 和請(qǐng)求體參數(shù)

首先,毫無(wú)疑問(wèn)地,你可以隨意地混合使用 Path、Query 和請(qǐng)求體參數(shù)聲明,F(xiàn)astAPI 會(huì)知道該如何處理。

你還可以通過(guò)將默認(rèn)值設(shè)置為 None 來(lái)將請(qǐng)求體參數(shù)聲明為可選參數(shù):

from typing import Optional

from fastapi import FastAPI, Path
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
    q: Optional[str] = None,
    item: Optional[Item] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results

Note

請(qǐng)注意,在這種情況下,將從請(qǐng)求體獲取的 item 是可選的。因?yàn)樗哪J(rèn)值為 None。

多個(gè)請(qǐng)求體參數(shù)

在上面的示例中,路徑操作將期望一個(gè)具有 Item 的屬性的 JSON 請(qǐng)求體,就像:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2
}

但是你也可以聲明多個(gè)請(qǐng)求體參數(shù),例如 item 和 user:

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


class User(BaseModel):
    username: str
    full_name: Optional[str] = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User):
    results = {"item_id": item_id, "item": item, "user": user}
    return results

在這種情況下,F(xiàn)astAPI 將注意到該函數(shù)中有多個(gè)請(qǐng)求體參數(shù)(兩個(gè) Pydantic 模型參數(shù))。

因此,它將使用參數(shù)名稱(chēng)作為請(qǐng)求體中的鍵(字段名稱(chēng)),并期望一個(gè)類(lèi)似于以下內(nèi)容的請(qǐng)求體:

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    },
    "user": {
        "username": "dave",
        "full_name": "Dave Grohl"
    }
}

Note

請(qǐng)注意,即使 item 的聲明方式與之前相同,但現(xiàn)在它被期望通過(guò) item 鍵內(nèi)嵌在請(qǐng)求體中。

FastAPI 將自動(dòng)對(duì)請(qǐng)求中的數(shù)據(jù)進(jìn)行轉(zhuǎn)換,因此 item 參數(shù)將接收指定的內(nèi)容,user 參數(shù)也是如此。

它將執(zhí)行對(duì)復(fù)合數(shù)據(jù)的校驗(yàn),并且像現(xiàn)在這樣為 OpenAPI 模式和自動(dòng)化文檔對(duì)其進(jìn)行記錄。

請(qǐng)求體中的單一值

與使用 Query 和 Path 為查詢(xún)參數(shù)和路徑參數(shù)定義額外數(shù)據(jù)的方式相同,F(xiàn)astAPI 提供了一個(gè)同等的 Body。

例如,為了擴(kuò)展先前的模型,你可能決定除了 item 和 user 之外,還想在同一請(qǐng)求體中具有另一個(gè)鍵 importance。

如果你就按原樣聲明它,因?yàn)樗且粋€(gè)單一值,F(xiàn)astAPI 將假定它是一個(gè)查詢(xún)參數(shù)。

但是你可以使用 Body 指示 FastAPI 將其作為請(qǐng)求體的另一個(gè)鍵進(jìn)行處理。

from typing import Optional

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


class User(BaseModel):
    username: str
    full_name: Optional[str] = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: int, item: Item, user: User, importance: int = Body(...)
):
    results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    return results

在這種情況下,F(xiàn)astAPI 將期望像這樣的請(qǐng)求體:

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    },
    "user": {
        "username": "dave",
        "full_name": "Dave Grohl"
    },
    "importance": 5
}

同樣的,它將轉(zhuǎn)換數(shù)據(jù)類(lèi)型,校驗(yàn),生成文檔等。

多個(gè)請(qǐng)求體參數(shù)和查詢(xún)參數(shù)

當(dāng)然,除了請(qǐng)求體參數(shù)外,你還可以在任何需要的時(shí)候聲明額外的查詢(xún)參數(shù)。

由于默認(rèn)情況下單一值被解釋為查詢(xún)參數(shù),因此你不必顯式地添加 Query,你可以?xún)H執(zhí)行以下操作:

q: str = None

比如:

from typing import Optional

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


class User(BaseModel):
    username: str
    full_name: Optional[str] = None


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Item,
    user: User,
    importance: int = Body(..., gt=0),
    q: Optional[str] = None
):
    results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    if q:
        results.update({"q": q})
    return results

Info

Body 同樣具有與 Query、Path 以及其他后面將看到的類(lèi)完全相同的額外校驗(yàn)和元數(shù)據(jù)參數(shù)。

嵌入單個(gè)請(qǐng)求體參數(shù)

假設(shè)你只有一個(gè)來(lái)自 Pydantic 模型 Item 的請(qǐng)求體參數(shù) item。

默認(rèn)情況下,F(xiàn)astAPI 將直接期望這樣的請(qǐng)求體。

但是,如果你希望它期望一個(gè)擁有 item 鍵并在值中包含模型內(nèi)容的 JSON,就像在聲明額外的請(qǐng)求體參數(shù)時(shí)所做的那樣,則可以使用一個(gè)特殊的 Body 參數(shù) embed:

item: Item = Body(..., embed=True)

比如:

from typing import Optional

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item = Body(..., embed=True)):
    results = {"item_id": item_id, "item": item}
    return results

在這種情況下,F(xiàn)astAPI 將期望像這樣的請(qǐng)求體:

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}

而不是:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2
}

總結(jié)

你可以添加多個(gè)請(qǐng)求體參數(shù)到路徑操作函數(shù)中,即使一個(gè)請(qǐng)求只能有一個(gè)請(qǐng)求體。

但是 FastAPI 會(huì)處理它,在函數(shù)中為你提供正確的數(shù)據(jù),并在路徑操作中校驗(yàn)并記錄正確的模式。

你還可以聲明將作為請(qǐng)求體的一部分所接收的單一值。

你還可以指示 FastAPI 在僅聲明了一個(gè)請(qǐng)求體參數(shù)的情況下,將原本的請(qǐng)求體嵌入到一個(gè)鍵中。


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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)