Pydantic:将默认字段定义为另一个字段的函数
我正在使用pydantic的数据类来创建一个不可变的数据类,这个数据类包含一个 name
(名字)、一个 label
(标签)和一个 id
(标识符)。我希望在创建 MyClass
对象时,可以指定标签,或者根据 name
的值来给一个默认的标签。
目前的实现方式只有在 label
是输入参数的一部分时才有效,代码如下:
@dataclass(frozen=True)
class MyClass
name: str = Field(default="class_name")
label: str = Field(default=None)
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
_validate_uuid = field_validator("id")(uuid_error)
@field_validator("label")
def set_default_label(cls, v, values):
if v is None:
v = foo(values["name"])
return v
...
使用这段代码,我们可以触发两种不同的行为:
MyClass(name="object_name", label=None)
返回的对象是 正确的:
MyClass(name="object_name", label=foo("object_name"),...)
但是如果我们依赖于 label
的默认值,比如使用下面的代码:
MyClass(name="object_name")
那么验证器就不会被调用,label
会保持为 None
:
MyClass(name="object_name", label=None)
1 个回答
1
在Pydantic中,如果不做额外的设置,默认值是不会被验证的。所以你需要在定义数据类的时候,传入相应的配置选项。看看下面这个例子:
from pydantic import Field, field_validator, ConfigDict
import uuid
from pydantic.dataclasses import dataclass
def foo(name):
return name + "_label"
@dataclass(config=ConfigDict(validate_default=True))
class MyClass:
name: str = Field(default="class_name")
label: str = Field(default=None)
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
@field_validator("label", mode="before")
@classmethod
def set_default_label(cls, v, info):
if v is None:
v = foo(info.data["name"])
return v
print(MyClass())
这个例子会输出:
MyClass(name='class_name', label='class_name_label', id='fda6cbe7-a756-4e93-9924-0cd024f59251')
另外,我觉得明确说明验证模式是个好主意,并且把验证声明为一个类方法。
希望这对你有帮助!