在 Python 中使用 Pydantic 的 BaseModel 进行数据验证

张开发
2026/4/17 2:44:22 15 分钟阅读

分享文章

在 Python 中使用 Pydantic 的 BaseModel 进行数据验证
在 Python 中使用 Pydantic 的 BaseModel 进行数据验证flyfishBaseModel 是什么拆字面意思Base Model 是什么Base字面基础的、基底的编程基类 / 父类—— 表示这是一个被继承的基础模板类不能直接拿来用必须让别的类继承它才能获得它的能力。Model字面模型编程数据模型—— 表示这是用来定义数据长什么样的抽象结构比如用户有姓名、年龄、邮箱订单有编号、金额、时间。# 必须继承它创建自己的 具体模型classUser(BaseModel):# User 是具体模型BaseModel 是它的基础name:strBase 基础、父类、模板只负责被继承不负责直接使用。名字部分含义作用Base基础父类类继承它获得校验/转换能力Model数据模型定义数据的结构和格式类型注解 给变量/参数贴一个 规定类型 的标签是一种语法标记Python 里的类型注解长这样# 变量名: 类型name:str小明age:int18is_student:boolTruestr 字符串文字int 整数数字bool 布尔值是/否冒号后面的str/int/bool就是类型注解。最简示例 继承BaseModel通过类型注解声明字段from pydanticimportBaseModel#2.定义数据模型继承 BaseModelclassUser(BaseModel):# 字段名:类型注解 name:str # 字符串类型 age:int# 整型 email:str # 字符串类型 #3.创建模型实例传入合法数据 userUser(name小明,age22,emailxiaomingexample.com)#4.访问模型属性和普通类一样print(用户名,user.name)print(年龄,user.age)#5.模型转字典Pydantic V2 推荐方法print(\n模型转字典,user.model_dump())#6.模型转 JSON 字符串print(模型转 JSON,user.model_dump_json())输出用户名 小明 年龄22模型转字典{name:小明,age:22,email:xiaomingexample.com}模型转 JSON{name:小明,age:22,email:xiaomingexample.com}静态语言自带编译期类型检查传错类型直接不让运行Python 是动态的没有编译检查类型错了只能运行时崩溃用 Python 写代码特别省事、速度特别快但它有个很头疼的问题不管是接口传进来的参数、配置文件里的内容还是咱们业务用到的数据都得自己手动写代码判断这个值是不是数字是不是文字格式规不规范Pydantic 这个工具就是专门解决这个麻烦的BaseModel 是它重要的功能它靠着 Python 自带的简单标注全自动检查数据、把数据转成正确的格式、还能轻松转换成接口需要的 JSON / 字典格式。自动数据校验当传入不合法数据时BaseModel会直接抛出清晰的验证错误frompydanticimportBaseModel,ValidationErrorclassUser(BaseModel):name:strage:intemail:str# 传入错误数据age 是字符串不符合 int 类型try:invalid_userUser(name小红,age二十二,# 非法数据emailxiaohongexample.com)# 捕获验证错误exceptValidationErrorase:print(数据验证失败)print(e)运行结果数据验证失败 1 validation error for User age Input should be a valid integer, unable to parse string as an integer [typeint_parsing, input_value二十二, input_typestr] For further information visit https://errors.pydantic.dev/2.12/v/int_parsing自动类型转换BaseModel会智能转换兼容类型如字符串数字 → 整型、数字 → 布尔值frompydanticimportBaseModelclassUser(BaseModel):name:strage:intis_vip:bool# 传入字符串数字、数字布尔值userUser(name小李,age25,# 字符串25 → 自动转为 int 25is_vip1# 数字1 → 自动转为 bool True)print(user.age,type(user.age))# 25 class intprint(user.is_vip,type(user.is_vip))# True class bool可选字段 默认值实际开发中很多字段是非必填的可以用Optional定义可选字段或直接设置默认值frompydanticimportBaseModelfromtypingimportOptional# 导入可选类型classUser(BaseModel):name:strage:int# 可选字段默认值为 Noneaddress:Optional[str]None# 普通默认值字段is_active:boolTrue# 不传入 address、is_active使用默认值userUser(name小王,age23)print(user.model_dump())# 输出{name: 小王, age: 23, address: None, is_active: True}嵌套数据模型复杂业务数据如用户地址支持嵌套模型BaseModel会递归校验所有嵌套数据frompydanticimportBaseModel# 子模型地址classAddress(BaseModel):province:strcity:strstreet:str# 父模型用户包含地址classUser(BaseModel):name:strage:intaddress:Address# 嵌套子模型# 创建嵌套实例userUser(name小张,age24,address{province:山东省,city:济南市,street:经十路})print(嵌套模型数据,user.address.city)# 深圳市print(完整字典,user.model_dump())运行结果嵌套模型数据 济南市 完整字典{name:小张,age:24,address:{province:山东省,city:济南市,street:经十路}}字段约束Field使用Field可以给字段添加长度、范围、描述等约束让校验更精细frompydanticimportBaseModel,Field,ValidationErrorclassUser(BaseModel):# 用户名长度2-20name:strField(min_length2,max_length20,description用户名)# 年龄0-150age:intField(gt0,lt150,description合法年龄)email:str# 测试非法数据名字太短年龄超标try:userUser(name张,age200,emailtestexample.com)exceptValidationErrorase:print(e.errors())运行结果[{type:string_too_short,loc:(name,),msg:String should have at least2characters, input: 张, ctx: {min_length: 2}, url: https://errors.pydantic.dev/2.12/v/string_too_short}, {type: less_than, loc: (age,), msg: Input should be less than 150, input: 200, ctx: {lt: 150}, url: https://errors.pydantic.dev/2.12/v/less_than}]自定义校验器field_validator对于复杂校验如邮箱格式、手机号格式可以用field_validator编写自定义验证逻辑frompydanticimportBaseModel,field_validator,ValidationErrorimportre# 正则表达式校验邮箱classUser(BaseModel):name:strage:intemail:str# 自定义邮箱校验器field_validator(email)defvalidate_email_format(cls,value):# 正则匹配标准邮箱格式ifnotre.match(r^[a-zA-Z0-9_.-][a-zA-Z0-9-]\.[a-zA-Z0-9-.]$,value):raiseValueError(邮箱格式不合法)returnvalue# 测试非法邮箱try:userUser(name小陈,age25,emailtest#example.com)exceptValidationErrorase:print(自定义校验错误,e.errors()[0][msg])# 输出自定义校验错误邮箱格式不合法禁止额外字段默认情况下BaseModel会忽略未定义的字段通过配置ConfigDict可以禁止传入额外字段避免脏数据frompydanticimportBaseModel,ConfigDict,ValidationErrorclassUser(BaseModel):name:strage:int# 模型配置禁止额外字段model_configConfigDict(extraforbid)# 传入未定义的字段 phone触发错误try:userUser(name小赵,age26,phone13800138000)exceptValidationErrorase:print(e运行结果1validation errorforUser phone Extra inputs arenotpermitted[typeextra_forbidden,input_value13800138000,input_typestr]

更多文章