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
是一个字符串字段且默认值为Gacfox
,hobbies
是一个字符串列表字段。如果创建该类实例传入的参数不符合要求,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]
使用Field
的default_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的,为了保持接口字段和数据模型字段命名风格的一致性,我们可以使用Field
的alias
属性来设置字段的别名,下面是一个例子。
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字符串解析为数据模型对象。
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_dump
和model_dump_json
方法来将数据模型对象序列化为dict
或JSON字符串。