本文將詳細介紹 Pydantic 模型 和 BaseModel 的核心概念,并通過實際代碼示例如何從零開始編寫自己的 Pydantic 模型。
1. Pydantic 是什么?
Pydantic 是一個 Python 庫,主要用于:
- 數據驗證:確保輸入數據符合預期的類型和約束。
- 數據解析:將 JSON、字典等原始數據轉換為 Python 對象。
- 文檔生成:自動生成 API 文檔(如 Swagger/OpenAPI)。
- 配置管理:安全地加載環境變量或配置文件。
2. BaseModel:所有模型的基類
Pydantic 的所有模型都繼承自 BaseModel
。它提供了核心功能:
- 自動驗證字段類型。
- 支持默認值和可選字段。
- 生成 JSON Schema(用于 API 文檔)。
基礎示例
from pydantic import BaseModelclass User(BaseModel):name: strage: int# 使用字典初始化
user_data = {"name": "Alice", "age": 25}
user = User(**user_data) # 自動驗證字段類型print(user.name) # 輸出: Alice
print(user.age) # 輸出: 25
3. 如何編寫自己的 Pydantic 模型?
(1) 定義字段類型
Pydantic 支持 Python 原生類型和復雜類型:
from typing import Optional, List
from datetime import datetime
import uuidclass Product(BaseModel):id: uuid.UUID # UUID 類型name: str # 必填字符串price: float # 浮點數tags: List[str] # 字符串列表created_at: datetime # 日期時間discount: Optional[float] = None # 可選字段
(2) 添加字段約束
使用 Field
定義更復雜的規則:
from pydantic import BaseModel, Fieldclass User(BaseModel):username: str = Field(..., min_length=3, max_length=20) # 必填,長度3-20email: str = Field(..., regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")age: int = Field(ge=18, description="必須成年") # 年齡 ≥ 18
(3) 自定義驗證邏輯
通過 @validator
添加自定義驗證:
from pydantic import validatorclass Payment(BaseModel):amount: floatcurrency: str@validator("amount")def amount_must_be_positive(cls, v):if v <= 0:raise ValueError("金額必須大于0")return v@validator("currency")def currency_must_be_valid(cls, v):if v not in ["USD", "EUR", "JPY"]:raise ValueError("無效的貨幣類型")return v
(4) 嵌套模型
模型可以嵌套其他模型:
class Address(BaseModel):city: strstreet: strclass Person(BaseModel):name: straddress: Address # 嵌套模型# 使用示例
data = {"name": "Bob","address": {"city": "New York", "street": "5th Ave"}
}
person = Person(**data)
4. 高級用法
(1) 配置模型行為
通過 Config
類自定義模型行為:
class ConfigExample(BaseModel):name: strclass Config:anystr_strip_whitespace = True # 自動去除字符串兩端空格allow_population_by_field_name = True # 允許用別名初始化extra = "forbid" # 禁止額外字段
(2) 生成 JSON Schema
Pydantic 自動為模型生成 JSON Schema:
print(User.schema_json(indent=2))
輸出:
{"title": "User","type": "object","properties": {"username": {"type": "string","minLength": 3,"maxLength": 20},"email": {"type": "string","pattern": "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"},"age": {"type": "integer","minimum": 18,"description": "必須成年"}},"required": ["username", "email", "age"]
}
(3) 與環境變量集成
從環境變量加載配置:
from pydantic import BaseSettingsclass Settings(BaseSettings):api_key: strdebug: bool = Falseclass Config:env_file = ".env" # 從.env文件加載settings = Settings() # 自動讀取環境變量
5. 完整示例:用戶注冊 API 模型
from pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional
from datetime import datetimeclass UserRegister(BaseModel):username: str = Field(..., min_length=3, max_length=20)email: EmailStr # 專門驗證郵箱格式的類型password: str = Field(..., min_length=8)birth_date: Optional[datetime] = Nonereferral_code: Optional[str] = Field(None, max_length=10)@validator("password")def password_must_contain_special_char(cls, v):if not any(c in "!@#$%^&*" for c in v):raise ValueError("密碼必須包含特殊字符")return v# 使用示例
user_data = {"username": "alice123","email": "alice@example.com","password": "secure!123"
}
user = UserRegister(**user_data) # 自動驗證
6. 常見問題解答
Q1:Pydantic 和 Dataclasses 有什么區別?
- Pydantic:專注于數據驗證和解析,支持復雜約束(如正則、自定義驗證)。
- Dataclasses:僅生成
__init__
和__repr__
,無驗證功能。
Q2:如何處理未知字段?
通過 Config
控制:
class Config:extra = "allow" # 允許額外字段(默認)extra = "forbid" # 禁止額外字段extra = "ignore" # 忽略額外字段
Q3:性能如何?
Pydantic 在首次運行時會生成驗證邏輯的優化代碼,后續調用速度接近原生 Python。
總結
功能 | 實現方式 |
---|---|
基礎字段定義 | name: str |
字段約束 | Field(..., min_length=3) |
自定義驗證 | @validator 裝飾器 |
嵌套模型 | 直接嵌套其他 BaseModel |
環境變量集成 | 繼承 BaseSettings + Config |
生成 API 文檔 | 自動通過 schema_json() 或 FastAPI 集成 |
通過 Pydantic,你可以用極少的代碼實現強大的數據驗證和轉換邏輯,非常適合 API 開發、配置管理和數據處理場景。