Skip to content
Advertisement

Pydantic created at and updated at fields

I’m new to using Pydantic and I’m using it to set up the models for FastAPI to integrate with my postgres database. I want to make a model that has an updated_at and created_at field which store the last datetime the model was updated and the datetime the model was created. I figured created_at could be something like this:

created_at: datetime = datetime.now()

How would I do an updated_at so it updates the datetime automatically every time the model is updated?

Advertisement

Answer

You can use a validator which will update the field updated_at each time when some other data in the model will change. The root_validator and the validate_assignment config attribute are what you are looking for.

This is the sample code:

from datetime import datetime
from time import sleep

from pydantic import BaseModel,root_validator


class Foo(BaseModel):
    data: str = "Some data"
    created_at: datetime = datetime.now()
    updated_at: datetime = datetime.now()

    class Config:
        validate_assignment = True

    @root_validator
    def number_validator(cls, values):
        values["updated_at"] = datetime.now()
        return values


if __name__ == '__main__':
    bar = Foo()
    print(bar.dict())
    sleep(5)
    bar.data = "New data"
    print(bar.dict())

and the output:

{
 'data': 'Some data',
 'created_at': datetime.datetime(2022, 7, 31, 10, 41, 13, 176243),
 'updated_at': datetime.datetime(2022, 7, 31, 10, 41, 13, 179253)
}

{
 'data': 'New data',
 'created_at': datetime.datetime(2022, 7, 31, 10, 41, 13, 176243),
 'updated_at': datetime.datetime(2022, 7, 31, 10, 41, 18, 184983)
}

You can see that there is a difference in microseconds after object creation. If this is a problem you can set:
updated_at: Optional[datetime] = None
and modify the validator like this:

    @root_validator
    def number_validator(cls, values):
        if values["updated_at"]:
            values["updated_at"] = datetime.now()
        else:
            values["updated_at"] = values["created_at"]
        return values

and the new output:

{
 'data': 'Some data',
 'created_at': datetime.datetime(2022, 7, 31, 10, 54, 33, 715379), 
 'updated_at': datetime.datetime(2022, 7, 31, 10, 54, 33, 715379)
}

{
 'data': 'New data',
 'created_at': datetime.datetime(2022, 7, 31, 10, 54, 33, 715379),
 'updated_at': datetime.datetime(2022, 7, 31, 10, 54, 38, 728778)
}
10 People found this is helpful
Advertisement