Pydantic:在将值分配给字段之前转换值?
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)
您可以像这样在 class 中实现它:
from pydantic import BaseModel, validator
class Window(BaseModel):
size: tuple[int, int]
_extract_size = validator('size', pre=True, allow_reuse=True)(transform)
注意传递给验证器的 pre=True
参数。这意味着它将 运行 before 默认验证器检查 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)
我有以下型号
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)
您可以像这样在 class 中实现它:
from pydantic import BaseModel, validator
class Window(BaseModel):
size: tuple[int, int]
_extract_size = validator('size', pre=True, allow_reuse=True)(transform)
注意传递给验证器的 pre=True
参数。这意味着它将 运行 before 默认验证器检查 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)