既然我們已經(jīng)知道了如何使用 Path 和 Query,下面讓我們來(lái)了解一下請(qǐng)求體聲明的更高級(jí)用法。
首先,毫無(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è)具有 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)行記錄。
與使用 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),生成文檔等。
當(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ù)。
假設(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
}
你可以添加多個(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è)鍵中。
更多建議: