在 Pydantic BaseModel 类中实例化后更改字段

17

以下是一个 Pydantic 类,我想通过应用 replace 操作转换 foo 字段:

```python class MyModel(BaseModel): foo: str @validator('foo') def replace_foo(cls, v): return v.replace('_', '-') ```
from typing import List
from pydantic import BaseModel

class MyModel(BaseModel):
    foo: List[str]

my_object = MyModel(foo="hello-there")
my_object.foo = [s.replace("-", "_") for s in my_object.foo]

当对象被创建时,我该如何在类内正确进行replace操作呢?如果没有Pydantic, 我只需在__init(self, foo)中完成, 但由于Pydantic会自动生成__init__实现, 所以我不确定应该如何继续进行。

3个回答

26

使用pydantic BaseModel

看起来您需要重写BaseModel的init方法,就像这样:

from typing import List
from pydantic import BaseModel

class MyModel(BaseModel):
    foo: List[str]

    def __init__(self, **data):
        data["foo"] = [s.replace("-", "_") for s in data["foo"]]
        super().__init__(**data)

my_object = MyModel(foo=["hello-there"])

print(my_object)
# Outputs foo=['hello_there']

使用Pydantic数据类

... 或者您还可以将其转换为Pydantic数据类,并使用Pydantic提供的post init dunder在实例化时执行其他操作。例如:

from typing import List
from pydantic.dataclasses import dataclass

@dataclass
class MyModel():
    foo: List[str]

    def __post_init__(self):
        self.foo = [s.replace("-", "_") for s in self.foo]

my_object = MyModel(foo=["hello-there"])

print(my_object)

# Outputs foo=['hello_there']

16

使用@validator装饰器(在这种情况下使用选项each_item=True,因为我们希望验证程序查看列表中的每个项目而不是列表本身):

from typing import List
from pydantic import BaseModel, validator

class MyModel(BaseModel):
    foo: List[str]

    @validator('foo', each_item=True)
    def replace_hyphen(cls,v):
        return v.replace("-","_")

my_object = MyModel(foo=["hello-there"])

print(my_object)
# Outputs foo=['hello_there']

或者如果您更喜欢dataclasses:

from typing import List
from pydantic import validator
from pydantic.dataclasses import dataclass

@dataclass
class MyModelDC():
    foo: List[str]

    @validator('foo', each_item=True)
    def replace_hyphen(cls,v):
        return v.replace("-","_")

my_objectDC = MyModelDC(foo=["hello-there"])

print(my_objectDC)
# Outputs foo=['hello_there']

非常好。each_item=True 这一部分听起来有点像“黑魔法”,但仍然非常方便。 - Jivan

12

Pydantic版本2.0+

根据文档,这是语法:

class MyModel(BaseModel):
    a: int
    b: str
    
    def model_post_init(self, __context) -> None:
        values = self.dict()
        # manipulation on fields

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接