Pydantic 数据验证讲解
文章目录
- 一、为什么需要 Pydantic?
- 二、安装
- 三、基础模型(BaseModel)
- 四、Field:更精细的控制
- 五、自定义验证器
- 1. 字段验证器(`field_validator`)
- 2. 模型级验证器(`model_validator`)
- 六、嵌套模型与复杂类型
- 七、配置管理(pydantic-settings)
- 八、常用进阶特性速览
- 九、与 FastAPI 的结合(预告)
- 十、最佳实践
Pydantic 是 Python 中最流行的数据验证与设置管理库,深度结合类型注解,能自动做类型转换、数据校验、生成文档和序列化。它是 FastAPI 的核心依赖,也广泛应用于配置管理、API 接口、数据处理等场景。
当前主流版本是Pydantic v2(性能大幅提升,API 更清晰)。
一、为什么需要 Pydantic?
传统手动验证:
defcreate_user(data:dict):if"name"notindataornotisinstance(data["name"],str):raiseValueError("name 必须是字符串")if"age"indataand(notisinstance(data["age"],int)ordata["age"]<0):raiseValueError("age 必须是非负整数")# ... 非常繁琐使用 Pydantic 后:
frompydanticimportBaseModelclassUser(BaseModel):name:strage:intuser=User(name="Alice",age=25)# 自动验证 + 转换print(user.name,user.age)优点:
- 声明式,代码简洁
- 自动类型转换(如
"25"→25) - 详细的错误信息
- 与 IDE / 类型检查器完美配合
- 支持 JSON 序列化/反序列化
- 可生成 JSON Schema
二、安装
pipinstallpydantic# 如果需要配置管理pipinstallpydantic-settings三、基础模型(BaseModel)
frompydanticimportBaseModel,FieldclassUser(BaseModel):name:strage:intemail:str|None=None# 可选字段is_active:bool=True# 默认值# 创建实例(自动验证)user=User(name="Alice",age="25")# 字符串 "25" 会自动转成 intprint(user)# name='Alice' age=25 email=None is_active=Trueprint(user.model_dump())# 转成字典(v2 推荐用法)print(user.model_dump_json())# 转成 JSON 字符串常用方法(Pydantic v2):
| 方法 | 作用 |
|---|---|
model_dump() | 转成 Python 字典 |
model_dump_json() | 转成 JSON 字符串 |
model_validate() | 从字典/对象创建并验证 |
model_validate_json() | 从 JSON 字符串创建并验证 |
model_json_schema() | 生成 JSON Schema |
四、Field:更精细的控制
frompydanticimportBaseModel,FieldclassUser(BaseModel):name:str=Field(min_length=2,max_length=50,description="用户名")age:int=Field(gt=0,lt=150,example=25)# gt=大于, lt=小于score:float=Field(default=0,ge=0,le=100)# ge=大于等于tags:list[str]=Field(default_factory=list)# 可变默认值用 default_factorypassword:str=Field(repr=False)# 不在 repr 中显示常用约束参数:
min_length/max_length(字符串、列表等)gt/ge/lt/le(数值)pattern(正则,字符串)default/default_factorydescription、example(用于文档生成)alias(别名,用于接收/输出不同字段名)
五、自定义验证器
1. 字段验证器(field_validator)
frompydanticimportBaseModel,field_validatorclassUser(BaseModel):name:strage:int@field_validator("name")@classmethoddefname_must_not_be_empty(cls,v:str)->str:ifnotv.strip():raiseValueError("姓名不能为空")returnv.strip().title()# 可顺便做转换@field_validator("age")@classmethoddefage_check(cls,v:int)->int:ifv<0:raiseValueError("年龄不能为负数")returnv2. 模型级验证器(model_validator)
用于跨字段校验:
frompydanticimportBaseModel,model_validatorclassRegisterForm(BaseModel):password:strconfirm_password:str@model_validator(mode="after")defcheck_passwords_match(self)->"RegisterForm":ifself.password!=self.confirm_password:raiseValueError("两次密码不一致")returnselfmode="before"在验证前处理原始数据,mode="after"在字段验证后处理。
六、嵌套模型与复杂类型
frompydanticimportBaseModelfromdatetimeimportdatetimeclassAddress(BaseModel):city:strstreet:strclassUser(BaseModel):name:straddress:Address# 嵌套模型tags:list[str]=[]metadata:dict[str,str]={}created_at:datetime user=User(name="Alice",address={"city":"北京","street":"中关村大街"},# 自动转成 Address 对象created_at="2026-08-24T12:00:00"# 自动解析时间)print(user.address.city)# 北京支持的类型非常丰富:list、dict、set、tuple、Optional、Union、Literal、自定义类等。
七、配置管理(pydantic-settings)
非常适合读取环境变量和.env文件:
frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):model_config=SettingsConfigDict(env_file=".env",env_file_encoding="utf-8",extra="ignore"# 忽略未定义的环境变量)app_name:str="MyApp"debug:bool=Falsedatabase_url:strmax_connections:int=10settings=Settings()print(settings.database_url)对应.env文件:
DATABASE_URL=postgresql://user:pass@localhost/db DEBUG=true八、常用进阶特性速览
| 特性 | 说明 |
|---|---|
Literal | 限制字段只能是特定值 |
EmailStr | 邮箱格式验证(需安装email-validator) |
HttpUrl | URL 验证 |
conint/constr等 | 带约束的类型(v2 更推荐用 Field) |
ConfigDict | 模型配置(frozen=True不可变、extra="forbid"禁止额外字段等) |
computed_field | 计算字段 |
model_serializer | 自定义序列化逻辑 |
TypeAdapter | 不需要完整模型也能验证简单类型 |
示例(禁止额外字段 + 不可变):
frompydanticimportBaseModel,ConfigDictclassUser(BaseModel):model_config=ConfigDict(extra="forbid",frozen=True)name:strage:int九、与 FastAPI 的结合(预告)
FastAPI 直接使用 Pydantic 模型做请求体验证和响应序列化:
fromfastapiimportFastAPIfrompydanticimportBaseModel app=FastAPI()classUserCreate(BaseModel):name:strage:int@app.post("/users/")defcreate_user(user:UserCreate):return{"message":f"创建用户{user.name}"}这就是为什么学 FastAPI 之前强烈建议先掌握 Pydantic。
十、最佳实践
- 优先使用类型注解 + Field 约束,少写手动 if 判断
- 可变默认值一定要用
default_factory - 生产环境建议设置
extra="forbid",防止多余字段悄悄进入 - 复杂校验优先用
field_validator/model_validator - 配置类继承
BaseSettings,业务数据模型继承BaseModel - v2 中统一使用
model_dump()、model_validate()等方法(旧的.dict()、.parse_obj()已弃用)
🚀 感谢阅读!想了解更多?
📖 我的博客网站 | 记录思考,分享干货
🏡 我的个人主页 | 关于我、开源项目
