Pydantic :资料验证的超强帮手

Pydantic 是 Python 中强型别资料验证与处理的标准工具,特别适合用于 API 的请求 / 回应资料结构验证。

1️⃣ 资料模型定义(BaseModel)

基本用法:定义一个「资料模型」,自动提供初始化、型别检查、序列化功能。

from pydantic import BaseModel

class User(BaseModel):
id: int
name: str
is_active: bool = True # 预设值

使用方式:

user = User(id=1, name="Alice")
print(user.model_dump()) # {'id': 1, 'name': 'Alice', 'is_active': True}

2️⃣ 自动验证(输入时)

自动验证资料类型与格式:

user = User(id="123", name="Bob")  # id 自动转换为 int
print(user.id) # 123

User(id="not_a_number", name="Bob")
# 🚨 ValueError: value is not a valid integer

3️⃣ 输出转换(dict / JSON / model_copy)

print(user.model_dump())       # 输出 Python dict
print(user.model_dump_json()) # 输出 JSON 字串
new_user = user.model_copy(update={"name": "Charlie"})

4️⃣ 自订栏位限制(Field)

使用 Field() 来指定:

  • 预设值 / 必填
  • 描述(给 API 文件看)
  • 长度、大小范围
  • 正则表达式
  • 限制值域
from pydantic import BaseModel, Field

class Product(BaseModel):
name: str = Field(..., min_length=2, max_length=50, description="商品名称")
price: float = Field(..., gt=0, description="价格需大于 0")
tag: str = Field(default="general", pattern="^[a-z_]+$")

示例输入:

Product(name="A", price=-5)
# 🚨 name 太短, price < 0 会报错

print(Product(name="Apple", price=10.5, tag="fruit").model_dump())
# {'name': 'Apple', 'price': 10.5, 'tag': 'fruit'}

5️⃣ Email、URL、IPv4、Decimal...:特化型别验证

Pydantic 提供大量内建型别:

from typing import Annotated
from pydantic import BaseModel, EmailStr, HttpUrl, IPvAnyAddress, condecimal

class Contact(BaseModel):
email: EmailStr
website: HttpUrl
ip: IPvAnyAddress
score: Annotated[float, condecimal(gt=0, lt=10)]

6️⃣ Optional / Union(选填与多型别)

from typing import Optional, Union

class Example(BaseModel):
note: Optional[str] # 可以是 str 或 None
value: Union[int, str] # 可以是 int 或 str
example = Example(note=None, value=42)
print(example.model_dump())  # {'note': None, 'value': 42}

7️⃣ 巢状模型(Nested Models)

class Address(BaseModel):
city: str
zipcode: str

class User(BaseModel):
name: str
address: Address

data = {
"name": "Tom",
"address": {
"city": "Taipei",
"zipcode": "100"
}
}
user = User(**data)
print(user.model_dump())  # {'name': 'Tom', 'address': {'city': 'Taipei', 'zipcode': '100'}}
print(user.address.city)  # 'Taipei'
print(user.address.zipcode)  # '100'
# 直接使用嵌套模型
print(user.model_dump_json(indent=2))  # 美化的 JSON 输出
# 嵌套模型的验证
# user = User(name="Alice", address={"city": "New York", "zipcode": "10001"})
# print(user.model_dump())  # {'name': 'Alice', 'address': {'city': 'New York', 'zipcode': '10001'}}

8️⃣ 自订栏位转换(validator)

使用 @field_validator(v2)或 @validator(v1) 来自订栏位逻辑:

from pydantic import BaseModel, field_validator

class User(BaseModel):
username: str

@field_validator("username")
@classmethod
def check_lowercase(cls, v):
if not v.islower():
raise ValueError("username 必须为小写")
return v

# 使用小写字母的 username
user = User(username="alice")
print(user.model_dump())  # {'username': 'alice'}

# 使用大写字母的 username
try:
    user = User(username="Alice")
except ValueError as e:
    print(e)  # username 必须为小写

9️⃣ 模型设定(Config)

自订模型的行为:

Pydantic v2 的设定方法:使用 model_config

from pydantic import BaseModel

class User(BaseModel):
name: str
age: int

model_config = {
"extra": "forbid", # 禁止多余栏位
"str_strip_whitespace": True, # 自动去除字串空白
"populate_by_name": True, # 允许用栏位别名填值
}
# 使用 model_config 来设定模型行为
user = User(name="Alice", age=30)
print(user.model_dump())  # {'name': 'Alice', 'age': 30}
print(user.model_config)  # {'extra': 'forbid', 'str_strip_whitespace': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

常用设定选项说明(v2)

🔚 总结表格

此篇了解FastAPI最核心的两大元件:Starlette、Pydantic的另一个Pydantic,Pydantic做为用来处理资料验证、序列化与型别安全的模型管理工具,使用 Python 类别定义资料模型、自动进行型别转换与资料验证、整合 FastAPI 等框架处理 API 输入/输出资料、支援巢状模型、栏位验证、自订逻辑等,是个还蛮完善的验证与处理工具。