[英]Pydantic: Transform a value before it is assigned to a field?
我有以下型号
class Window(BaseModel):
size: tuple[int, int]
我想像这样实例化它:
fields = {'size': '1920x1080'}
window = Window(**fields)
当然这会失败,因为'size'
的值不是正确的类型。 但是,我想添加逻辑,以便在x
处拆分值,即:
def transform(raw: str) -> tuple[int, int]:
x, y = raw.split('x')
return int(x), int(y)
Pydantic 支持这个吗?
您可以使用 pydantic 的validator
来实现这样的行为。 给定您的预定义功能:
def transform(raw: str) -> tuple[int, int]:
x, y = raw.split('x')
return int(x), int(y)
你可以像这样在你的类中实现它:
from pydantic import BaseModel, validator
class Window(BaseModel):
size: tuple[int, int]
_extract_size = validator('size', pre=True, allow_reuse=True)(transform)
注意传递给验证器的pre=True
参数。 这意味着它将在检查size
是否为元组的默认验证器之前运行。
现在:
fields = {'size': '1920x1080'}
window = Window(**fields)
print(window)
# output: size=(1920, 1080)
请注意,在那之后,您将无法使用大小的元组来实例化您的Window
。
fields2 = {'size': (800, 600)}
window2 = Window(**fields2)
# AttributeError: 'tuple' object has no attribute 'split'
为了克服这个问题,如果通过稍微更改代码来传递元组,您可以简单地绕过该函数:
def transform(raw: str) -> tuple[int, int]:
if type(raw) == tuple:
return raw
x, y = raw.split('x')
return int(x), int(y)
哪个应该给出:
fields2 = {'size': (800, 600)}
window2 = Window(**fields2)
print(window2)
# output: size:(800, 600)
只是为了分享一个基于 convtools 的替代方案:
from convtools.contrib.models import (
DictModel,
build,
casters,
validate,
validators,
)
class Window(DictModel):
size: tuple[int, int] = (
validate(validators.Type(str))
.cast(casters.CustomUnsafe(lambda s: s.split("x")))
.cast()
)
obj, errors = build(Window, {"size": "1920x1080"})
# In [12]: obj
# Out[12]: Window(size=(1920, 1080))
obj, errors = build(Window, {"size": "1920 1080"})
# In [14]: errors
# Out[14]: {'size': {'__ERRORS': {'length': 'not enough values to unpack (expected 2, got 1)'}}}
或者,如果需要自定义方法:
class Window(DictModel):
size: tuple[int, int] = field(cls_method=True)
@classmethod
def get_size(cls, data):
try:
x, y = data["size"].split("x")
return (int(x), int(y)), None
except Exception: # this is bad, but this is only an example
return None, {"invalid_size": True}
文档: https ://convtools.readthedocs.io/en/latest/models.html
Github: https ://github.com/westandskif/convtools
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.