rayon
rayon

Reputation: 600

Triggering a function on creation of an pydantic object

is there a clean way of triggering a function call whenever I create/ instantiate a pydantic object?

Currently I am "misusing" the root_validator for this:

from pydantic import BaseModel

class PydanticClass(BaseModel):
  name: str

  @root_validator()
  def on_create(cls, values):
    print("Put your logic here!")
    return values

So on PydanticClass(name="Test") executes my logic and simply returns the same object values.

This works but I have two issues, which is why I would be interested in a cleaner solution:

  1. I basically don't do a validation (return the same values).
  2. I think this function will also be executed once the object is changed, which I don't want.

So I am happy to learn about any better approaches/ solutions.

Upvotes: 7

Views: 9395

Answers (4)

nimrod serok
nimrod serok

Reputation: 16033

If you want this function to compute a value in your pydantic object, since pydantic V2 you can use the @computed_field decorator. You can even use it to call another function...

from pydantic import BaseModel, computed_field


class MyModel(BaseModel):
    name: str
    
    @computed_field
    def presented_name(self) -> str:
                  # you can even call here another function...
        return self.name + '\n'

Upvotes: 0

alex_noname
alex_noname

Reputation: 32163

Your intentions are not fully clear. But I can suggest overriding the __init__ model method. In this case, your code will be executed once at object instantiation:

from pydantic import BaseModel


class PydanticClass(BaseModel):
  name: str

  def __init__(self, **data) -> None:
      super().__init__(**data)
      print("Put your logic here!")

Upvotes: 11

Teej
Teej

Reputation: 380

As of Pydantic v2, you can now override the model_post_init method.

from pydantic import BaseModel


class PydanticClass(BaseModel):
  name: str

  def model_post_init(self, ctx):
      print("Put your logic here!")

Upvotes: 8

Tzane
Tzane

Reputation: 3462

You could use python dataclass __post_init__:

from pydantic.dataclasses import dataclass

@dataclass
class PydanticClass:
    name: str

    def __post_init__(self):
        print("Post init")

pc = PydanticClass(name="Test")
print(pc)

post_init is called once after __init__ so it wouldn't be called after changes to the class instance are made.

Upvotes: 2

Related Questions