Model类

Python泛型类

TypeVar 是一个泛型类型变量,使用 bound 参数来限制所生成的类型的继承关系。

from typing import Generic, TypeVar

from pydantic import BaseModel

# T只能是BaseModel或者int类型
TypeX = TypeVar('TypeX', BaseModel, int)


class BaseClass(BaseModel, Generic[TypeX]):
    X: TypeX

# 子类必须也继承Generic[TypeX]
class ChildClass(BaseClass[TypeX], Generic[TypeX]):
    # Inherit from Generic[TypeX]
    pass

Model.construct跳过验证

使用默认构造函数创建对象会对属性进行校验,如果我们不希望进行校验,可以使用model.construct方法,使用该方法需要注意以下几点

  1. 既然跳过了数据验证,pydantic也会跳过将字典对象转化为模型的步骤,意味着对于对象类型的属性,我们提供给model_construct的需要是对象类型。
  2. 不支持递归构造,只会解析一层。
  3. 如果传入了多余的属性并且extra设置为allow,多余的属性被存储到__pydantic_extra__。
  4. 如果模型存在私有属性,__pydantic_private__字典的初始化与调用__init__方法一样。
  5. 使用model_construct不会调用任何__init__方法。

综上,非必要不建议使用该方法。

动态创建Model类

根据运行时信息的不同,我们可能有不同的模型属性和校验规则,这个时候就需要动态创建Model类了。

from pydantic import BaseModel, create_model

DynamicFoobarModel = create_model(
    'DynamicFoobarModel', foo=(str, ...), bar=(int, 123)
)


class StaticFoobarModel(BaseModel):
    foo: str
    bar: int = 123

def username_alphanumeric(cls, v):
    assert v.isalnum(), 'must be alphanumeric'
    return v
# 定义校验器
validators = {
    'username_validator': field_validator('username')(username_alphanumeric)
}

UserModel = create_model(
    'UserModel', username=(str, ...), __validators__=validators, 
    # 父类
    __base__=StaticFooBarModel
)

类属性和私有属性

  • 对象可访问类属性,但不可修改
  • 私有属性必须以下划线开头,不会被序列化
class Model(BaseModel):
    x: int = 2
    y: ClassVar[int] = 1
	_processed_at: datetime = PrivateAttr(default_factory=datetime.now)
    _secret_value: str
	
	def __init__(self, **data):
        super().__init__(**data)
        # this could also be done with default_factory
        self._secret_value = randint(1, 5)
m = Model()
print(m)
print(m.y)
print(Model.y)
m.y += 1 # error

Q.E.D.


一切很好,不缺烦恼。