1.复合类型
from uuid import UUID
from typing import Union
from pydantic import BaseModel
class User(BaseModel):
id: Union[UUID, int, str]
name: str
user_03_uuid = UUID('cf57432e-809e-4353-adbd-9d5c0d733868')
user_03 = User(id=user_03_uuid, name='John Doe')
print(user_03)
#> id=UUID('cf57432e-809e-4353-adbd-9d5c0d733868') name='John Doe'
print(user_03.id)
#> cf57432e-809e-4353-adbd-9d5c0d733868
print(user_03_uuid.int)
#> 275603287559914445491632874575877060712
2.限制复合型
from typing import Literal, Union
from pydantic import BaseModel, Field, ValidationError
class Cat(BaseModel):
pet_type: Literal['cat']
meows: int
class Dog(BaseModel):
pet_type: Literal['dog']
barks: float
class Lizard(BaseModel):
pet_type: Literal['reptile', 'lizard']
scales: bool
class Model(BaseModel):
# discriminator定义限制字段
pet: Union[Cat, Dog, Lizard] = Field(..., discriminator='pet_type')
n: int
print(Model(pet={'pet_type': 'dog', 'barks': 3.14}, n=1))
try:
Model(pet={'pet_type': 'dog'}, n=1)
except ValidationError as e:
print(e)
"""
1 validation error for Model
pet -> Dog -> barks
field required (type=value_error.missing)
"""
3.嵌套限制复合型
from typing import Literal, Union
from typing_extensions import Annotated
from pydantic import BaseModel, Field, ValidationError
class BlackCat(BaseModel):
pet_type: Literal['cat']
color: Literal['black']
black_name: str
class WhiteCat(BaseModel):
pet_type: Literal['cat']
color: Literal['white']
white_name: str
# Can also be written with a custom root type
#
# class Cat(BaseModel):
# __root__: Annotated[Union[BlackCat, WhiteCat], Field(discriminator='color')]
Cat = Annotated[Union[BlackCat, WhiteCat], Field(discriminator='color')]
class Dog(BaseModel):
pet_type: Literal['dog']
name: str
Pet = Annotated[Union[Cat, Dog], Field(discriminator='pet_type')]
class Model(BaseModel):
pet: Pet
n: int
m = Model(pet={'pet_type': 'cat', 'color': 'black', 'black_name': 'felix'}, n=1)
print(m)
#> pet=BlackCat(pet_type='cat', color='black', black_name='felix') n=1
try:
Model(pet={'pet_type': 'cat', 'color': 'red'}, n='1')
except ValidationError as e:
print(e)
"""
1 validation error for Model
pet -> Union[BlackCat, WhiteCat]
No match for discriminator 'color' and value 'red' (allowed values:
'black', 'white')
(type=value_error.discriminated_union.invalid_discriminator;
discriminator_key=color; discriminator_value=red; allowed_values='black',
'white')
"""
try:
Model(pet={'pet_type': 'cat', 'color': 'black'}, n='1')
except ValidationError as e:
print(e)
"""
1 validation error for Model
pet -> Union[BlackCat, WhiteCat] -> BlackCat -> black_name
field required (type=value_error.missing)
"""
4.枚举和选择
from enum import Enum, IntEnum
from pydantic import BaseModel, ValidationError
class FruitEnum(str, Enum):
pear = 'pear'
banana = 'banana'
class ToolEnum(IntEnum):
spanner = 1
wrench = 2
class CookingModel(BaseModel):
fruit: FruitEnum = FruitEnum.pear
tool: ToolEnum = ToolEnum.spanner
print(CookingModel(tool=2, fruit='banana'))
try:
CookingModel(fruit='other')
except ValidationError as e:
print(str(e))
"""
1 validation error for CookingModel
fruit
value is not a valid enumeration member; permitted: 'pear', 'banana' (type=type_error.enum; enum_values=[<FruitEnum.pear: 'pear'>, <FruitEnum.banana: 'banana'>])
"""
5.日期时间类型
datetime
:支持datetime
对象、str
、int
时间戳from datetime import datetime
# from tzlocal import get_localzone
from pydantic import BaseModel
class Model(BaseModel):
dt: datetime = None
dt = datetime.now()
# dt = datetime.now(tz=get_localzone())
# 将datetime转为str
str_dt = dt.strftime('%Y-%m-%d %H:%M:%S.%f')
# 将str转为datetime
# dt2 = datetime.strptime(str_dt, '%Y-%m-%d %H:%M:%S.%f')
# 将datetime转为时间戳
dt_stamp = datetime.timestamp(dt)
# 将时间戳转换为datetime
# dt3 = datetime.fromtimestamp(dt_stamp, get_localzone())
# m = Model(dt=dt)
# m = Model(dt=str_dt)
m = Model(dt=dt_stamp)
print(m.json())
date
:支持date和datetime
对象、str
、int
时间戳from datetime import datetime, date
from pydantic import BaseModel
class Model(BaseModel):
d: date = None
d = datetime.now()
# 将datetime转为str
str_d = dt.strftime('%Y-%m-%d')
# 将datetime转为时间戳
d_stamp = datetime.timestamp(dt)
m = Model(d=d)
# m = Model(d=d.date())
# m = Model(d=str_d)
# m = Model(d=d_stamp)
print(m.json())
time
:支持time
对象、str
from datetime import datetime, time
from pydantic import BaseModel
class Model(BaseModel):
t: time = None
t = datetime.now().time()
# 将datetime转为str
str_t = datetime.now().strftime('%H:%M:%S.%f')
m = Model(t=t)
# m = Model(t=str_t)
print(m.json())
timedelta
:支持timedelta
对象、str
、int
from datetime import timedelta
from pydantic import BaseModel
class Model(BaseModel):
td: timedelta = None
# timedelta
td = timedelta(days=1, hours=3, minutes=10)
# str
# [-][DD ][HH:MM]SS[.ffffff] | [±]P[DD]DT[HH]H[MM]M[SS]S
# str_td = "P3DT12H30M5S"
# str_td = "3 29:18:39"
str_td = "1 10:48:27.112324"
# int
int_td = 36000
# m = Model(td=td)
m = Model(td=str_td)
# m = Model(td=int_td)
print(m.dict())
6.布尔值
布尔值
:True
、False
整形
:0、1
字符串
:'0', 'off', 'f', 'false', 'n', 'no'
和 '1', 'on', 't', 'true', 'y', 'yes'
- 如果想要严格约束布尔值只能接收
False
和True
,请使用StrictBool
from pydantic import BaseModel
class BooleanModel(BaseModel):
bool_value: bool
print(BooleanModel(bool_value='no'))
7.文本类型
- 这是python标准库从python 3.8开始的新功能
- 此字段类型的一个优点是,它可用于检查与一个或多个特定值的相等性,而无需声明自定义验证程序,可以代替枚举类型
# from typing_extensions import Literal python < 3.8 时使用
from typing import Literal
from pydantic import BaseModel, ValidationError
class Pie(BaseModel):
flavor: Literal['apple', 'pumpkin']
Pie(flavor='apple')
Pie(flavor='pumpkin')
try:
Pie(flavor='cherry')
except ValidationError as e:
print(str(e))
"""
1 validation error for Pie
flavor
unexpected value; permitted: 'apple', 'pumpkin'
(type=value_error.const; given=cherry; permitted=('apple', 'pumpkin'))
"""
8.TypedDict类型
- 这是 python 标准库自 python 3.8 起的新功能。在python 3.8之前,它需要打字扩展包。但是,自python 3.9以来,必填字段和可选字段才得到正确区分。因此,我们建议在python 3.8中使用打字扩展
from typing_extensions import TypedDict
from pydantic import BaseModel, Extra, ValidationError
# `total=False` 标识这两个字段非必要
class UserIdentity(TypedDict, total=False):
name: str
surname: str
class User(TypedDict):
identity: UserIdentity
age: int
class Model(BaseModel):
u: User
class Config:
# 禁止传递额外字段
extra = Extra.forbid
# print(Model(u={'identity': {'name': 'Smith', 'surname': 'John'}, 'age': '37'}))
# u={'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
# print(Model(u={'identity': {'name': None, 'surname': 'John'}, 'age': '37'}))
# u={'identity': {'name': None, 'surname': 'John'}, 'age': 37}
# print(Model(u={'identity': {}, 'age': '37'}))
# u={'identity': {}, 'age': 37}
try:
# 类型错误
Model(u={'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': '24'})
except ValidationError as e:
print(e)
"""
1 validation error for Model
u -> identity -> name
str type expected (type=type_error.str)
"""
try:
# 多余的字段email
Model(
u={
'identity': {'name': 'Smith', 'surname': 'John'},
'age': '37',
'email': 'john.smith@me.com',
}
)
except ValidationError as e:
print(e)
"""
1 validation error for Model
u -> email
extra fields not permitted (type=value_error.extra)
"""
9.Pydantic Types
FilePath
:like ,但路径必须存在并且是文件Path
DirectoryPath
:like ,但路径必须存在并且是一个目录Path
PastDate
:like ,但日期应该是过去的date
FutureDate
:like,,但日期应该在将来date
EmailStr
:需要安装电子邮件验证器;输入字符串必须是有效的电子邮件地址,输出是简单字符串
NameEmail
:需要安装电子邮件验证器;输入字符串必须是有效的电子邮件地址或格式,并且输出是具有两个属性的对象:NameEmail(name='dupuffer', email='dupuffer@outlook.com')
PyObject
:需要一个字符串并加载可在该虚线路径上导入的python对象;例如,如果提供了,则生成的字段值将是函数'math.cos'cosfrom pydantic import BaseModel, PyObject
class Model(BaseModel):
e: PyObject
m = Model(e="builtins.ord")
print(m.e('a'))
Color
:用于解析HTML和CSS颜色;请参阅颜色类型
Json
:一个特殊的类型包装器,在解析之前加载JSON
PaymentCardNumber
:用于解析和验证支付卡
AnyUrl
:任何网址
AnyHttpUrl
:一个 HTTP 网址
HttpUrl
:更严格的HTTP网址from pydantic import BaseModel, HttpUrl, PostgresDsn, ValidationError, validator
class MyModel(BaseModel):
url: HttpUrl
m = MyModel(url='http://www.example.com')
# the repr() method for a url will display all properties of the url
print(repr(m.url))
# HttpUrl('http://www.example.com', scheme='http', host='www.example.com',
# tld='com', host_type='domain', port='80')
print(m.url.scheme)
# http
print(m.url.host)
# www.example.com
print(m.url.host_type)
# domain
print(m.url.port)
FileUrl
:文件路径网址
PostgresDsn
:一个postgres DSN样式的URL
RabbitMqDsn
:RabbitMQ,StormMQ,ActiveMQ等使用的DSN样式URL
RedisDsn
:RedisDsn
stricturl
:任意URL约束的类型方法
UUID1
:需要类型 1 的有效 UUID
UUID3
:需要类型 3 的有效 UUID
UUID4
:需要类型 4 的有效 UUID
UUID5
:需要类型 5 的有效 UUID
SecretBytes
:字节,其中值保持部分机密
SecretStr
:值部分保密的字符串
IPvAnyAddress
:允许IPv4AddressIPv6Address
IPvAnyInterface
:允许IPv4InterfaceIPv6Interface
IPvAnyNetwork
:允许IPv4NetworkIPv6Network
NegativeFloat
:允许负的浮点数;使用标准解析,然后检查值是否小于0;请参见约束类型float
NegativeInt
:允许一个负的整数;使用标准解析,然后检查值是否小于0;请参见约束类型int
PositiveFloat
:允许正的浮点数;使用标准解析,然后检查值是否大于0;请参见约束类型float
PositiveInt
:允许正整数;使用标准解析,然后检查值是否大于0;请参见约束类型int
conbytes
:用于约束字节的类型方法
condecimal
:用于约束小数的文字方法
confloat
:用于约束浮点数的类型方法
conint
:用于约束 ints 的类型方法
conlist
:用于约束列表的类型方法
conset
:用于约束集合的类型方法
confrozenset
:用于约束冻结集的类型方法
constr
:用于约束 strs 的类型方法
10.颜色类型
名称
:例如,"Black"、"azure"
十六进制值
:例如,"0x000"、"#FFFFFF"、"7fffd4"
RGB/RGBA 元组
:例如,(255, 255, 255)、(255, 255, 255, 0.5)
RGB/RGBA 字符串
:例如,"rgb(255, 255, 255)"、"rgba(255, 255, 255, 0.5)"
HSL 字符串
:例如,"hsl(270, 60%, 70%)"、"hsl(270, 60%, 70%, .5)"
from pydantic import BaseModel, ValidationError
from pydantic.color import Color
c = Color('ff00ff')
print(c.as_named())
#> magenta
print(c.as_hex())
#> #f0f
c2 = Color('green')
print(c2.as_rgb_tuple())
#> (0, 128, 0)
print(c2.original())
#> green
print(repr(Color('hsl(180, 100%, 50%)')))
#> Color('cyan', rgb=(0, 255, 255))
class Model(BaseModel):
color: Color
print(Model(color='purple'))
#> color=Color('purple', rgb=(128, 0, 128))
try:
Model(color='hello')
except ValidationError as e:
print(e)
"""
1 validation error for Model
color
value is not a valid color: string not recognised as a valid color
(type=value_error.color; reason=string not recognised as a valid color)
"""
11.密钥类型
- 可以使用 和 数据类型来存储不希望在日志记录或回溯中可见的敏感信息。 并且可以完全初始化,也可以分别使用 或 文本 进行初始化。和 将被格式化为或转换为 json 时
from pydantic import BaseModel, SecretStr, SecretBytes
class SimpleModel(BaseModel):
password: SecretStr
password_bytes: SecretBytes
sm = SimpleModel(password='IAmSensitive', password_bytes=b'IAmSensitiveBytes')
print(sm.password) # **********
print(sm.password_bytes) # **********
print(sm.json())
# {"password": "**********", "password_bytes": "**********"}
# 获取真实数据
print(sm.password.get_secret_value()) # IAmSensitive
print(sm.password_bytes.get_secret_value()) # b'IAmSensitiveBytes'
# If you want the secret to be dumped as plain-text using the json method,
# you can use json_encoders in the Config class.
class SimpleModelDumpable(BaseModel):
password: SecretStr
password_bytes: SecretBytes
class Config:
# 在调用json方法时会对值进行解析
json_encoders = {
SecretStr: lambda v: v.get_secret_value() if v else None,
SecretBytes: lambda v: v.get_secret_value() if v else None,
}
sm2 = SimpleModelDumpable(password='IAmSensitive', password_bytes=b'IAmSensitiveBytes')
print(sm2.password) # **********
print(sm2.dict())
"""
{
'password': SecretStr('**********'),
'password_bytes': SecretBytes(b'**********'),
}
"""
#
# But the json method will
print(sm2.json())
"""
{
"password": "IAmSensitive",
"password_bytes": "IAmSensitiveBytes"
}
"""
12.Json类型
from typing import List
from pydantic import BaseModel, Json, ValidationError
class SimpleJsonModel(BaseModel):
json_obj: Json
class ComplexJsonModel(BaseModel):
json_obj: Json[List[int]]
# obj = SimpleJsonModel(json_obj='{"b": 1}')
# print(type(obj.json_obj)) # dict
# print(obj.json_obj) # {'b': 1}
# obj2 = ComplexJsonModel(json_obj='[1, 2, 3]')
# print(type(obj2.json_obj)) # list
# print(obj2.json_obj) # [1, 2, 3]
try:
ComplexJsonModel(json_obj='["a", "b"]')
except ValidationError as e:
print(e)
"""
2 validation errors for ComplexJsonModel
json_obj -> 0
value is not a valid integer (type=type_error.integer)
json_obj -> 1
value is not a valid integer (type=type_error.integer)
"""
13.字节大小
- 使用数据类型将字节字符串表示形式转换为原始字节,并打印出人类可读的字节版本
from pydantic import BaseModel, ByteSize
class MyModel(BaseModel):
size: ByteSize
print(MyModel(size=52000).size)
# 52000
print(MyModel(size='3000 KiB').size)
# 3000 * 1024 = 3072000
m = MyModel(size='50 PB') # 1PB = 1000TB 1PiB = 1024TiB
print(m.size / 1024 / 1024 / 1024 / 1024 / 1024) # 44.40892098500626
# 将bytes格式化
print(m.size.human_readable())
# 44.4PiB
print(m.size.human_readable(decimal=True))
# 50.0PB
print(m.size / 1024 / 1024 / 1024 / 1024) # 45474.73508864641
print(m.size.to('TiB')) # # 45474.73508864641