在 Pydantic 模型中,我想根据第三个字段包含的值设置两个字段的值。但我还想设置一些微妙的别名。
所以如果我们有:
class FooModel(BaseModel):
data_holder: list = Field(..., exclude=True)
# Values of bar and baz below will be set based on values in data_holder
bar: int = Field(..., validation_alias=AliasChoices(‘bar’, ‘Bar’), serialization_alias=‘Bar’)
baz: int = Field(..., validation_alias=AliasChoices(‘baz’, ‘Baz’), serialization_alias=‘Baz’)
我也这样做:
foo = FooModel(data_holder=[123, 456])
我想要:
# The model will compute:
bar=123 # Field validation and serialization rules apply
baz=456 # Field validation and serialization rules apply
# Such that:
print(bar)
#> Bar='123'
print(baz)
#> Baz='456'
--> 使用
@computed_field
可以做到这一点吗,或者还有其他推荐的方法吗?
root_validator
在 V1 中提供了解决方案,但已被弃用。我也考虑过使用“之前”field_validator
,但还没有让它适用于我的实际用例。 (现实世界的环境更加混乱,data_holder
实际上是另一个 Pydantic 模型)。
这似乎与您要问的非常接近:
class FooModel(BaseModel):
data_holder: list[int] = Field(exclude=True)
@computed_field(alias='Bar')
def bar(self) -> int:
return self.data_holder[0]
@computed_field(alias='Baz')
def baz(self) -> int:
return self.data_holder[1]
data_holder
用于实例化,Bar
和Baz
用于序列化:
foo = FooModel(data_holder=[123, 456])
print(foo)
# -> FooModel(data_holder=[123, 456], bar=123, baz=456)
foo.model_dump(by_alias=True)
# -> {'Bar': 123, 'Baz': 456}
这是我的理解:
validation_alias
仅用于实例化/加载,serialization_alias
用于转储,alias
是两者的简写,但如果提供,则其他优先。FooModel.bar
和 FooModel.baz
是根据 FooModel.data_holder
计算的。如果在实例化期间提供,它们将被忽略,因此 validation_alias
将毫无意义,并且 serialization_alias
隐含于 alias
。因此,只有 alias
可用于 @computed_field()
。exclude=True
上的 data_holder
确保在转储时始终将其排除,但它在类实例上仍然可用。print()
,如果您想隐藏 data_holder
或显示 bar
和 baz
的别名,则需要覆盖 .__repr__()
或 .__repr_args__()
。.model_dump()
,您也可以覆盖 by_alias=True
。