本文将详细介绍 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 开发、配置管理和数据处理场景。