欢迎光临
我们一直在努力

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

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

flyfish

BaseModel 是什么?
拆字面意思:Base + Model 是什么?

  • Base
    字面:基础的、基底的
    编程:基类 / 父类 —— 表示这是一个被继承的基础模板类,不能直接拿来用,必须让别的类继承它,才能获得它的能力。
  • Model
    字面:模型
    编程:数据模型 —— 表示这是用来定义数据长什么样的抽象结构(比如:用户有姓名、年龄、邮箱;订单有编号、金额、时间)。
  • # 必须继承它,创建自己的 具体模型
    class User(BaseModel): # User 是具体模型,BaseModel 是它的基础
    name: str

    Base = 基础、父类、模板,只负责被继承,不负责直接使用。

    名字部分含义作用
    Base 基础父类 类继承它,获得校验/转换能力
    Model 数据模型 定义数据的结构和格式

    类型注解 = 给变量/参数贴一个 规定类型 的标签是一种语法标记
    Python 里的类型注解,长这样:

    # 变量名: 类型
    name: str = "小明"
    age: int = 18
    is_student: bool = True

    str = 字符串(文字)
    int = 整数(数字)
    bool = 布尔值(是/否)

    冒号后面的 str/int/bool,就是类型注解。

    最简示例 继承 BaseModel,通过类型注解声明字段

    from pydantic import BaseModel

    # 2. 定义数据模型,继承 BaseModel
    class User(BaseModel):
    # 字段名: 类型注解
    name: str # 字符串类型
    age: int # 整型
    email: str # 字符串类型

    # 3. 创建模型实例(传入合法数据)
    user = User(
    name="小明",
    age=22,
    email="xiaoming@example.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': 'xiaoming@example.com'}
    模型转 JSON: {"name":"小明","age":22,"email":"xiaoming@example.com"}

    静态语言自带编译期类型检查,传错类型直接不让运行
    Python 是动态的,没有编译检查,类型错了只能运行时崩溃

    用 Python 写代码特别省事、速度特别快,但它有个很头疼的问题,不管是接口传进来的参数、配置文件里的内容,还是咱们业务用到的数据,都得自己手动写代码判断:这个值是不是数字?是不是文字?格式规不规范?
    Pydantic 这个工具,就是专门解决这个麻烦的!BaseModel 是它重要的功能,它靠着 Python 自带的简单标注,全自动检查数据、把数据转成正确的格式、还能轻松转换成接口需要的 JSON / 字典格式。

    自动数据校验

    当传入不合法数据时,BaseModel 会直接抛出清晰的验证错误

    from pydantic import BaseModel, ValidationError

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

    # 传入错误数据:age 是字符串,不符合 int 类型
    try:
    invalid_user = User(
    name="小红",
    age="二十二", # 非法数据
    email="xiaohong@example.com"
    )
    # 捕获验证错误
    except ValidationError as e:
    print("数据验证失败:")
    print(e)

    运行结果:

    数据验证失败:
    1 validation error for User
    age
    Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='二十二', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/int_parsing

    自动类型转换

    BaseModel 会智能转换兼容类型(如字符串数字 → 整型、数字 → 布尔值)

    from pydantic import BaseModel

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

    # 传入字符串数字、数字布尔值
    user = User(
    name="小李",
    age="25", # 字符串"25" → 自动转为 int 25
    is_vip=1 # 数字1 → 自动转为 bool True
    )

    print(user.age, type(user.age)) # 25 <class 'int'>
    print(user.is_vip, type(user.is_vip)) # True <class 'bool'>

    可选字段 + 默认值

    实际开发中,很多字段是非必填的,可以用 Optional 定义可选字段,或直接设置默认值:

    from pydantic import BaseModel
    from typing import Optional # 导入可选类型

    class User(BaseModel):
    name: str
    age: int
    # 可选字段:默认值为 None
    address: Optional[str] = None
    # 普通默认值字段
    is_active: bool = True

    # 不传入 address、is_active,使用默认值
    user = User(name="小王", age=23)
    print(user.model_dump())
    # 输出:{'name': '小王', 'age': 23, 'address': None, 'is_active': True}

    嵌套数据模型

    复杂业务数据(如用户+地址)支持嵌套模型,BaseModel 会递归校验所有嵌套数据

    from pydantic import BaseModel

    # 子模型:地址
    class Address(BaseModel):
    province: str
    city: str
    street: str

    # 父模型:用户(包含地址)
    class User(BaseModel):
    name: str
    age: int
    address: Address # 嵌套子模型

    # 创建嵌套实例
    user = User(
    name="小张",
    age=24,
    address={
    "province": "山东省",
    "city": "济南市",
    "street": "经十路"
    }
    )

    print("嵌套模型数据:", user.address.city) # 深圳市
    print("完整字典:", user.model_dump())

    运行结果:

    嵌套模型数据: 济南市
    完整字典: {'name': '小张', 'age': 24, 'address': {'province': '山东省', 'city': '济南市', 'street': '经十路'}}

    字段约束(Field)

    使用 Field 可以给字段添加长度、范围、描述等约束,让校验更精细:

    from pydantic import BaseModel, Field, ValidationError

    class User(BaseModel):
    # 用户名:长度2-20
    name: str = Field(min_length=2, max_length=20, description="用户名")
    # 年龄:0-150
    age: int = Field(gt=0, lt=150, description="合法年龄")
    email: str

    # 测试非法数据:名字太短,年龄超标
    try:
    user = User(name="张", age=200, email="test@example.com")
    except ValidationError as e:
    print(e.errors())

    运行结果:

    [{'type': 'string_too_short', 'loc': ('name',), 'msg': 'String should have at least 2 characters', '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 编写自定义验证逻辑:

    from pydantic import BaseModel, field_validator, ValidationError
    import re # 正则表达式校验邮箱

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

    # 自定义邮箱校验器
    @field_validator('email')
    def validate_email_format(cls, value):
    # 正则匹配标准邮箱格式
    if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$', value):
    raise ValueError("邮箱格式不合法")
    return value

    # 测试非法邮箱
    try:
    user = User(name="小陈", age=25, email="test#example.com")
    except ValidationError as e:
    print("自定义校验错误:", e.errors()[0]["msg"])
    # 输出:自定义校验错误:邮箱格式不合法

    禁止额外字段

    默认情况下,BaseModel 会忽略未定义的字段;通过配置 ConfigDict 可以禁止传入额外字段,避免脏数据:

    from pydantic import BaseModel, ConfigDict,ValidationError

    class User(BaseModel):
    name: str
    age: int
    # 模型配置:禁止额外字段
    model_config = ConfigDict(extra="forbid")

    # 传入未定义的字段 phone,触发错误
    try:
    user = User(name="小赵", age=26, phone="13800138000")
    except ValidationError as e:
    print(e

    运行结果:

    1 validation error for User
    phone
    Extra inputs are not permitted [type=extra_forbidden, input_value='13800138000', input_type=str]

    赞(0)
    未经允许不得转载:171主机测评 » 在 Python 中使用 Pydantic 的 BaseModel 进行数据验证
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址