pydantic字段类型

1.复合类型

  • Union,支持将多种类型作为可选项
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.限制复合型

  • Literal:需要python3.8
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对象、strint时间戳
    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对象、strint时间戳
    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对象、strint
    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.布尔值

  • 布尔值TrueFalse
  • 整形:0、1
  • 字符串'0', 'off', 'f', 'false', 'n', 'no''1', 'on', 't', 'true', 'y', 'yes'
  • 如果想要严格约束布尔值只能接收FalseTrue,请使用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'cos
    from 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类型

  • 自动将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
posted @ 2022-06-15 17:55  fatpuffer  阅读(1196)  评论(0编辑  收藏  举报