請求本文¶
當你需要從用戶端(例如瀏覽器)將資料傳送到你的 API 時,會把它作為請求本文送出。
請求本文是用戶端傳給你的 API 的資料。回應本文是你的 API 傳回給用戶端的資料。
你的 API 幾乎總是需要傳回回應本文。但用戶端不一定每次都要送出請求本文,有時只會請求某個路徑,可能帶一些查詢參數,但不會傳送本文。
要宣告請求本文,你會使用 Pydantic 模型,享受其完整的功能與優點。
Info
要傳送資料,應使用下列其中一種方法:POST(最常見)、PUT、DELETE 或 PATCH。
在規範中,於 GET 請求中攜帶本文的行為是未定義的。不過,FastAPI 仍支援它,但僅適用於非常複雜/極端的情境。
由於不建議這麼做,使用 Swagger UI 的互動式文件在使用 GET 時不會顯示本文的文件,而且中間的代理伺服器也可能不支援。
匯入 Pydantic 的 BaseModel¶
首先,從 pydantic 匯入 BaseModel:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
建立你的資料模型¶
接著,你將資料模型宣告為繼承自 BaseModel 的類別。
對所有屬性使用標準的 Python 型別:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
就和宣告查詢參數時一樣,當模型屬性有預設值時,它就不是必填;否則就是必填。使用 None 可使其成為選填。
例如,上述模型對應的 JSON「object」(或 Python dict)如下:
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
...由於 description 與 tax 是選填(預設為 None),以下這個 JSON「object」也有效:
{
"name": "Foo",
"price": 45.2
}
將它宣告為參數¶
要把它加到你的路徑操作(path operation)中,宣告方式與路徑與查詢參數相同:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
...並將其型別宣告為你建立的模型 Item。
效果¶
只靠這樣的 Python 型別宣告,FastAPI 會:
- 將請求本文讀取為 JSON。
- (必要時)轉換為對應的型別。
- 驗證資料。
- 若資料無效,會回傳清楚易懂的錯誤,指出哪裡、哪筆資料不正確。
- 把接收到的資料放在參數
item中提供給你。- 由於你在函式中將其宣告為
Item型別,你也會獲得完整的編輯器支援(自動完成等)以及所有屬性與其型別。
- 由於你在函式中將其宣告為
- 為你的模型產生 JSON Schema 定義,如有需要,你也可以在專案中的其他地方使用。
- 這些 schema 會成為產生的 OpenAPI schema 的一部分,並由自動文件 UIs 使用。
自動文件¶
你的模型的 JSON Schema 會納入產生的 OpenAPI schema,並顯示在互動式 API 文件中:

也會用於每個需要它們的路徑操作內的 API 文件:

編輯器支援¶
在編輯器裡、於你的函式中,你會在各處獲得型別提示與自動完成(如果你接收的是 dict 而不是 Pydantic 模型,就不會有這些):

你也會獲得對不正確型別操作的錯誤檢查:

這不是偶然,整個框架就是圍繞這個設計而建。
而且在實作之前的設計階段就已徹底測試,確保能在各種編輯器中運作良好。
甚至為了支援這點,Pydantic 本身也做了些修改。
前面的螢幕截圖是使用 Visual Studio Code 拍的。
但你在 PyCharm 與大多數其它 Python 編輯器中也會得到相同的編輯器支援:

Tip
如果你使用 PyCharm 作為編輯器,可以安裝 Pydantic PyCharm Plugin。
它能增強 Pydantic 模型的編輯器支援,包含:
- 自動完成
- 型別檢查
- 重構
- 搜尋
- 程式碼檢查
使用該模型¶
在函式內,你可以直接存取模型物件的所有屬性:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.model_dump()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
請求本文 + 路徑參數¶
你可以同時宣告路徑參數與請求本文。
FastAPI 會辨識出與路徑參數相符的函式參數應該從路徑取得,而宣告為 Pydantic 模型的函式參數應該從請求本文取得。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_id": item_id, **item.model_dump()}
請求本文 + 路徑 + 查詢參數¶
你也可以同時宣告本文、路徑與查詢參數。
FastAPI 會分別辨識並從正確的位置取得資料。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
result = {"item_id": item_id, **item.model_dump()}
if q:
result.update({"q": q})
return result
函式參數的辨識方式如下:
- 如果參數同時在路徑中宣告,則作為路徑參數。
- 如果參數是單一型別(像是
int、float、str、bool等),會被視為查詢參數。 - 如果參數宣告為 Pydantic 模型 型別,會被視為請求本文。
Note
FastAPI 會因為預設值 = None 而知道 q 的值不是必填。
str | None 並非 FastAPI 用來判斷是否必填的依據;它會因為有預設值 = None 而知道不是必填。
但加入這些型別註解能讓你的編輯器提供更好的支援與錯誤偵測。
不使用 Pydantic¶
若你不想使用 Pydantic 模型,也可以使用 Body 參數。請參考Body - 多個參數:本文中的單一值。