既然我們已經(jīng)知道了如何使用 Path 和 Query,下面讓我們來了解一下請求體聲明的更高級用法。
首先,毫無疑問地,你可以隨意地混合使用 Path、Query 和請求體參數(shù)聲明,F(xiàn)astAPI 會知道該如何處理。
你還可以通過將默認(rèn)值設(shè)置為 None 來將請求體參數(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
請注意,在這種情況下,將從請求體獲取的 item 是可選的。因為它的默認(rèn)值為 None。
在上面的示例中,路徑操作將期望一個具有 Item 的屬性的 JSON 請求體,就像:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
但是你也可以聲明多個請求體參數(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ù)中有多個請求體參數(shù)(兩個 Pydantic 模型參數(shù))。
因此,它將使用參數(shù)名稱作為請求體中的鍵(字段名稱),并期望一個類似于以下內(nèi)容的請求體:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
}
}
Note
請注意,即使 item 的聲明方式與之前相同,但現(xiàn)在它被期望通過 item 鍵內(nèi)嵌在請求體中。
FastAPI 將自動對請求中的數(shù)據(jù)進(jìn)行轉(zhuǎn)換,因此 item 參數(shù)將接收指定的內(nèi)容,user 參數(shù)也是如此。
它將執(zhí)行對復(fù)合數(shù)據(jù)的校驗,并且像現(xiàn)在這樣為 OpenAPI 模式和自動化文檔對其進(jìn)行記錄。
與使用 Query 和 Path 為查詢參數(shù)和路徑參數(shù)定義額外數(shù)據(jù)的方式相同,F(xiàn)astAPI 提供了一個同等的 Body。
例如,為了擴(kuò)展先前的模型,你可能決定除了 item 和 user 之外,還想在同一請求體中具有另一個鍵 importance。
如果你就按原樣聲明它,因為它是一個單一值,F(xiàn)astAPI 將假定它是一個查詢參數(shù)。
但是你可以使用 Body 指示 FastAPI 將其作為請求體的另一個鍵進(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 將期望像這樣的請求體:
{
"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ù)類型,校驗,生成文檔等。
當(dāng)然,除了請求體參數(shù)外,你還可以在任何需要的時候聲明額外的查詢參數(shù)。
由于默認(rèn)情況下單一值被解釋為查詢參數(shù),因此你不必顯式地添加 Query,你可以僅執(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 以及其他后面將看到的類完全相同的額外校驗和元數(shù)據(jù)參數(shù)。
假設(shè)你只有一個來自 Pydantic 模型 Item 的請求體參數(shù) item。
默認(rèn)情況下,F(xiàn)astAPI 將直接期望這樣的請求體。
但是,如果你希望它期望一個擁有 item 鍵并在值中包含模型內(nèi)容的 JSON,就像在聲明額外的請求體參數(shù)時所做的那樣,則可以使用一個特殊的 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 將期望像這樣的請求體:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
}
而不是:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
你可以添加多個請求體參數(shù)到路徑操作函數(shù)中,即使一個請求只能有一個請求體。
但是 FastAPI 會處理它,在函數(shù)中為你提供正確的數(shù)據(jù),并在路徑操作中校驗并記錄正確的模式。
你還可以聲明將作為請求體的一部分所接收的單一值。
你還可以指示 FastAPI 在僅聲明了一個請求體參數(shù)的情況下,將原本的請求體嵌入到一個鍵中。
更多建議: