前言
- 接口傳參方式之一:通過發送請求體(Request Body)來傳遞請求數據
- 在 FastAPI,提倡使用 Pydantic 模型來定義請求體
- 這篇文章會詳細講不使用 Pydantic 和 使用 Pydantic 發送請求體的栗子
注意
- 請求體並不是只有 POST 請求有,只不過 POST 更常見
- 在 PUT、DELETE、PATCH 請求中都可以使用請求體
- 其實,在 GET 請求中也可以用請求體,不過僅適用於非常極端的情況下,而且 Swagger API 並不會顯示 GET 請求的請求體
不使用 Pydantic的栗子
from fastapi import FastAPI import uvicorn app = FastAPI() @app.post("/items") async def read_item(item: dict): return {"item": item} if __name__ == "__main__": uvicorn.run(app="6_request:app", host="127.0.0.1", port=8080, reload=True, debug=True)
指定查詢參數的類型為 dict
正確傳參的請求結果
查看請求頭
是 json 格式,符合預期
重點
- 用 postman 發起請求的話,一定要選 JSON 格式哦
- 因為接收的是 dict,所以 FastAPI 會自動將 JSON 字符串轉換為 dict
- 這種場景下,雖然查詢參數叫 item,但請求體的字段名可以隨意取,字段數量也可以任意個
錯誤傳參的請求結果
選了 text 之后,因為不是 JSON 字符串,FastAPI 無法正確解析請求體為 dict,所以會報類型錯誤的提示
查看請求頭
類型是 text
用 Dict 代替 dict 的栗子
Dict 是 typing 模塊提供的類,可以指定鍵值對的數據類型
from typing import Dict from fastapi import FastAPI app = FastAPI() @app.post("/Dict/") # 鍵為 str,值為 float async def create_index_weights(weights: Dict[str, float]): return weights
使用 Dict 相比直接用 dict 的好處
聲明為 Dict[str, float],FastAPI 會對每一個鍵值對都做數據校驗,校驗失敗會有友好的錯誤提示
正確傳參的請求結果
校驗失敗的請求結果
友好的錯誤提示啊~
使用 Pydantic 模型(建議使用)
實際栗子
from fastapi import FastAPI from typing import Optional from pydantic import BaseModel app = FastAPI() # 自定義一個 Pydantic 模型 class Item(BaseModel): name: str description: Optional[str] = None price: float tax: Optional[float] = None @app.post("/items/") # item 參數的類型指定為 Item 模型 async def create_item(item: Item): return item
參數指定為 Pydantic 模型后,FastAPI 做了這幾件事
- 將請求體識別為 JSON 字符串
- 將字段值轉換相應的類型(若有需要)
- 驗證數據,如果驗證失敗,會返回一個清晰的錯誤,准確指出錯誤數據的位置和信息
- item 會接收到完整的請求體數據,擁有所有屬性及其類型,IDE 也會給予對應的智能提示
- 給 Pydantic 模型自動的生成 JSON Schema,這些 Schema 會成為生成 OpenAPI Schema 的一部分,並顯示在接口文檔上
正確傳參的請求結果
正常傳參,所有屬性按指定的類型進行傳數據
字段值類型自動轉換
- name: str 傳了 bool 類型的數據
- description: str 傳了 float 類型的數據
- price: float 傳了 int 類型的數據
- tax: float 傳了 bool 類型的數據
FastAPi 會將傳進來的值自動轉換為指定類型的值
- 將 true 轉成 str 類型,即 "True"
- 將 12.22 轉成 str 類型,即 "12.22"
- 將 12 轉成 float 類型,即 12.0
- 將 true 轉成 float 類型,即 1.0
如果轉換失敗,則會報 type_error 錯誤(如下圖)
驗證數據失敗的請求結果
查看 Swagger API 文檔
Schema 部分
model 的 JSON Schema 會成為 Swagger APi 文檔的一部分
示例值部分
IDE 智能提示
因為知道 name 屬性的類型是 str,所以 IDE 會智能提示 str 內置的方法
Request body + path + query parameters 綜合栗子
- 可以同時聲明請求體、路徑參數、查詢參數
- FastAPI 可以識別出它們中的每一個,並從正確的位置獲取到數據
實際代碼
from typing import Optional from fastapi import FastAPI from pydantic import BaseModel class Item(BaseModel): name: str description: Optional[str] = None price: float tax: Optional[float] = None app = FastAPI() @app.put("/items/{item_id}") async def create_item( # 路徑參數 item_id: int, # 請求體,模型類型 item: Item, # 查詢參數 name: Optional[str] = None): result = {"item_id": item_id, **item.dict()} print(result) if name: # 如果查詢參數 name 不為空,則替換掉 item 參數里面的 name 屬性值 result.update({"name": name}) return result
FastAPI 識別參數的邏輯
- 如果參數也在路徑中聲明,它將解釋為路徑參數【item_id】
- 如果參數是單數類型(如int、float、str、boo l等),它將被解釋為查詢參數【name】
- 如果參數被聲明為 Pydantic 模型的類型,它將被解析為請求體【item】
正確傳參的請求結果
Pycharm Console 輸出結果
打印 result 的值
{'item_id': 1234, 'name': '小菠蘿', 'description': '描述,非必填', 'price': 12.22, 'tax': 0.0}
查看 Swagger API 文檔