1. 什麼是請求體?¶
在Web開發中,我們經常需要處理客戶端發送的數據。FastAPI中,當客戶端通過POST、PUT等方法發送複雜數據(比如JSON格式)時,這些數據會被放在請求體(Request Body)中。和通過URL傳遞的查詢參數(Query Parameters)不同,請求體更適合傳遞結構化數據(如用戶信息、表單等)。
舉個例子:用戶註冊時,我們需要收集姓名、年齡、地址等信息,這些數據如果用查詢參數會顯得冗長且不安全,因此通常放在請求體中。
2. Pydantic是什麼?¶
Pydantic是FastAPI推薦使用的數據驗證和解析庫。它允許我們定義數據結構(如用戶信息、商品信息),並自動進行數據類型檢查、格式驗證,還能將請求體數據轉換爲Python對象。
簡單來說,Pydantic就像一個“數據保鏢”,確保你收到的數據符合預期格式,避免因數據錯誤導致的API異常。
3. 定義第一個Pydantic模型¶
首先,我們需要安裝Pydantic(FastAPI已內置,若未安裝可通過pip install pydantic安裝)。然後,通過繼承pydantic.BaseModel來定義數據模型。
示例1:簡單模型(無嵌套)
from pydantic import BaseModel
# 定義一個User模型,包含name和age字段
class User(BaseModel):
name: str # 字符串類型,必填
age: int # 整數類型,必填
# FastAPI接口:接收User模型作爲請求體
from fastapi import FastAPI
app = FastAPI()
@app.post("/users/")
def create_user(user: User):
# FastAPI會自動解析請求體爲User對象
return {"message": f"用戶 {user.name} 創建成功!年齡:{user.age}"}
測試這個接口:
用Postman或curl發送POST請求到http://localhost:8000/users/,請求體爲JSON:
{
"name": "小明",
"age": 20
}
接口會返回成功信息:{"message": "用戶 小明 創建成功!年齡:20"}。
4. 複雜數據結構:嵌套模型¶
當數據包含子結構時(比如用戶有地址信息),我們可以在模型中嵌套其他Pydantic模型。
示例2:嵌套模型(用戶+地址)
from pydantic import BaseModel
from typing import Optional # 用於可選字段
# 先定義子模型:地址
class Address(BaseModel):
street: str # 街道
city: str # 城市
zipcode: str = "100000" # 可選,默認值
# 定義主模型:用戶(嵌套Address)
class User(BaseModel):
name: str
age: int
address: Optional[Address] = None # 地址是可選的(Optional+默認None)
@app.post("/users/with-address/")
def create_user_with_address(user: User):
# 訪問嵌套字段:user.address.street
return {
"name": user.name,
"address": user.address.dict() if user.address else "無地址"
}
測試:
請求體中加入地址信息:
{
"name": "小紅",
"age": 22,
"address": {
"street": "科技路100號",
"city": "北京"
}
}
接口返回:{"name": "小紅", "address": {"street": "科技路100號", "city": "北京", "zipcode": "100000"}}。
5. 複雜數據結構:列表類型¶
如果需要接收多個同類數據(如用戶的興趣愛好列表),可以用List類型(需導入typing.List)。
示例3:列表類型(興趣愛好列表)
from pydantic import BaseModel
from typing import List, Optional
class User(BaseModel):
name: str
age: int
hobbies: List[str] = [] # 字符串列表,默認空列表
extra_info: Optional[dict] = None # 可選字典(比如額外信息)
@app.post("/users/with-hobbies/")
def create_user_with_hobbies(user: User):
return {
"name": user.name,
"hobbies": user.hobbies,
"extra_info": user.extra_info if user.extra_info else "無額外信息"
}
測試:
請求體包含列表:
{
"name": "小剛",
"age": 25,
"hobbies": ["籃球", "編程"],
"extra_info": {"height": 180, "weight": 70}
}
接口返回:{"name": "小剛", "hobbies": ["籃球", "編程"], "extra_info": {"height": 180, "weight": 70}}。
6. 複雜數據結構:嵌套列表¶
如果列表中包含其他模型(比如多個商品),可以用List[模型名]。
示例4:嵌套列表(商品列表)
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
class Order(BaseModel):
order_id: int
items: List[Item] # 列表中的每個元素是Item模型
@app.post("/orders/")
def create_order(order: Order):
total = sum(item.price for item in order.items)
return {
"order_id": order.order_id,
"items": [item.dict() for item in order.items],
"total_price": total
}
測試:
請求體包含嵌套列表:
{
"order_id": 1001,
"items": [
{"name": "蘋果", "price": 5.0},
{"name": "香蕉", "price": 3.0}
]
}
接口返回總價格:{"order_id": 1001, "items": [{"name": "蘋果", "price": 5.0}, {"name": "香蕉", "price": 3.0}], "total_price": 8.0}。
7. 數據驗證:自動攔截錯誤數據¶
Pydantic會自動檢查數據是否符合模型定義。如果數據類型錯誤(比如age寫成字符串),FastAPI會返回422 Validation Error。
示例5:驗證失敗測試
發送錯誤請求體(age是字符串):
{
"name": "小麗",
"age": "20", # 錯誤類型:字符串而非整數
"hobbies": ["畫畫"]
}
接口會返回錯誤:
{
"detail": [
{
"loc": ["body", "age"],
"msg": "輸入值不是整數",
"type": "type_error.integer"
}
]
}
8. 總結¶
- 請求體:適合傳遞複雜數據(如JSON),通過POST/PUT方法發送。
- Pydantic:定義數據結構、自動驗證、減少手動解析代碼。
- 嵌套模型:用
模型名作爲字段類型實現子結構(如用戶+地址)。 - 列表/字典:支持
List和dict類型,滿足多數據項需求。 - 自動驗證:不符合模型的請求會被FastAPI自動攔截,返回清晰錯誤信息。
掌握Pydantic是FastAPI處理複雜請求體的核心技能,能讓你的API開發更規範、更健壯。
(注:所有代碼可直接在FastAPI項目中運行,需安裝fastapi和uvicorn:pip install fastapi uvicorn,運行命令:uvicorn main:app --reload)