pydantic 数据模型验证库

pydantic是Python中的一个数据模型和字段验证库,它提供了一种简单的方式来定义和使用数据模型并能够自动对数据字段进行验证,很多最新的Python框架如FastAPI等都是基于pydantic构建的,使用pydantic能够达到简化代码、提升代码可读性的目的。pydantic的功能非常强大,我们这里只介绍一些常见的基础用法,没有提到的部分具体可以参考相关文档。

官方文档:https://docs.pydantic.dev/latest/

Github地址:https://github.com/pydantic/pydantic

注意:pydantic分为v1和v2两个版本,这两个版本有较大区别,新版本中许多老的用法被废弃了,最新的v2版本发布于2023年,我们这里以新版本为例进行介绍。

安装和基本使用

执行以下命令使用pip包管理工具安装pydantic库。

pip install pydantic

我们这里编写一个简单的例子来演示pydantic的基本用法。

from datetime import datetime

from pydantic import BaseModel, ValidationError


class User(BaseModel):
    """用户数据模型"""
    id: int
    name: str
    create_time: datetime


try:
    # 创建用户对象
    user = User(id=1, name='John', create_time=datetime.now())
    # 序列化为JSON并打印
    user_data_dict = user.model_dump()
    print(user_data_dict)
except ValidationError as e:
    print(e.errors())

上面代码中我们定义了一个User类,注意它和基础的Python类是不同的,我们的User类继承了pydantic的BaseModel类并全部使用类属性定义其中的字段,这个基类赋予了我们pydantic中有关数据验证、序列化等诸多强大功能。创建User类的实例时,我们传入了它所需的参数,如果参数类型不符合要求,pydantic将抛出ValidationError,我们可以基于此来对数据模型进行验证。

模型和字段定义

基础用法

pydantic模型继承BaseModel来定义,使用类属性指定模型的字段,并使用Python的类型标注来标定字段的数据类型供pydantic框架验证。

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = 'Gacfox'
    hobbies: list[str]


user = User(id=1, name="Gacfox", hobbies=["coding", "sleeping"])
print(user.model_dump())

上面代码中,id是一个整数字段,name是一个字符串字段且默认值为Gacfoxhobbies是一个字符串列表字段。如果创建该类实例传入的参数不符合要求,ValidationError异常将被抛出。

模型嵌套

数据模型是可以嵌套的,下面是一个例子。

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = 'Gacfox'
    hobbies: list[str]


class Room(BaseModel):
    id: int
    name: str
    users: list[User]


user = User(id=1, name="Gacfox", hobbies=["coding", "sleeping"])
room = Room(id=1, name="My room", users=[user])

字段默认值

设置字段默认值的一种方式是直接使用类属性的默认值,指定默认值后,创建对象时如果未提供该属性,则会使用默认值。

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = 'Gacfox'
    hobbies: list[str]

此外我们也可以使用Field对象来详细设置字段的各种配置信息,下面指定默认值的效果和前面相同。

from pydantic import BaseModel, Field


class User(BaseModel):
    id: int
    name: str = Field(default='Gacfox')
    hobbies: list[str]

使用Fielddefault_factory属性可以指定一个函数来生成默认值,下面例子中,id字段的默认值由uuid4().hex生成。

from uuid import uuid4

from pydantic import BaseModel, Field


class User(BaseModel):
    id: str = Field(default_factory=lambda: uuid4().hex)

在最新的Python版本(3.9及以上)我们还可以使用Annotated来设置Field信息,下面例子和上面代码等效。

from uuid import uuid4

from typing import Annotated

from pydantic import BaseModel, Field


class User(BaseModel):
    id: Annotated[str, Field(default_factory=lambda: uuid4().hex)]

可选字段

使用默认值可以实现一个字段是可选的,下面是一个例子。

from pydantic import BaseModel


class User(BaseModel):
    user_id: str | None = None

注意:在Python3.10之前不支持str | None写法,此时可以使用Optional[str]Union[str, None]来代替。

字段别名

Python的变量命名规范是Snake Case的,但有时我们的接口字段等是Camel Case的,为了保持接口字段和数据模型字段命名风格的一致性,我们可以使用Fieldalias属性来设置字段的别名,下面是一个例子。

from pydantic import BaseModel, Field


class User(BaseModel):
    user_id: str = Field(alias='userId')


user = User(userId='Gacfox')
print(user.model_dump())

设置别名后,我们创建对象时就必须使用这个别名来创建,否则会抛出ValidationError异常。

排除字段

指定exclude=True可以在序列化时排除一个字段,下面例子中extra_data字段在序列化时会被排除在外。

from pydantic import BaseModel, Field


class User(BaseModel):
    user_id: str = Field(alias='userId')
    extra_data: str = Field(exclude=True)

字段验证

Pydantic的Field对象提供了大量内置的数据验证属性,不过我们这里不会逐一列举,具体使用参考官方文档即可,下面是一个简单的例子。

from pydantic import BaseModel, Field


class User(BaseModel):
    name: str
    age: int = Field(ge=0, le=200)

代码中,我们验证了age字段是一个整数,且其大小在0到200之间。

自定义字段验证逻辑

pydantic也支持自定义字段验证逻辑,下面是一个例子。

from pydantic import BaseModel, field_validator


class User(BaseModel):
    name: str

    @field_validator('name')
    @classmethod
    def name_validator(cls, v: str) -> str:
        if len(v) < 3:
            raise ValueError('Name must be at least 3 characters')
        return v

代码中我们使用了@field_validator装饰器,其中指定要验证的字段名,之后我们创建了一个classmethod并在其中对字段进行校验,校验不通过时抛出ValueError异常。name_validator(cls, v: str) -> str函数中,cls是类本身,v是我们要校验的字段的值。

解析和序列化为JSON

下面例子演示如何将JSON字符串解析为数据模型对象。

import json

from pydantic import BaseModel, Field


class User(BaseModel):
    id: int
    name: str = Field(default='Gacfox')
    hobbies: list[str]


json_str = '{"id":1,"name":"Gacfox","hobbies":["coding","sleeping"]}'
user = User(**json.loads(json_str))
print(user)

代码中我们使用**操作符将dict中的键值对解包,并传递给User类。

下面例子展示如何将数据模型对象序列化为dict或JSON字符串。

from pydantic import BaseModel, Field


class User(BaseModel):
    id: int
    name: str = Field(default='Gacfox')
    hobbies: list[str]


user = User(id=1, name='Gacfox', hobbies=['coding', 'sleeping'])
# 转为dict
print(user.model_dump())
# 序列化为JSON字符串
print(user.model_dump_json())

代码中,我们分别调用了model_dumpmodel_dump_json方法来将数据模型对象序列化为dict或JSON字符串。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap