I'm experimenting with SQLModel as an ORM. A few of my models have custom validation, calculated fields, or just things that I want to happen when they're created or changed. I end up using the following boilerplate a lot:
class MyModel(SqlModel):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.custom_method()
def update(self, **kwargs):
super().update(**kwargs)
self.custom_method()
def custom_method(self):
"""Do this when a model is created or updated
"""
pass
Is there some nice way I can sweeten this syntax a little? Ideally I'd like a decorator around the function that would inject the function call into __init__
and update
:
class MyModel(SqlModel):
@run_on_change
def custom_method(self):
"""Do this when a model is created or updated
"""
pass
But I can't figure out how this would work, since a decorator intercepts when a function is called and modifies its behaviour, whereas I want to modify the circumstances in which the function is called.
Alternatively, can anyone make a compelling argument for using a @listens_for
decorator instead of the above boilerplate approach associated with the model itself?
Define an abstract base class to act as the bridge between SQLModel
and your concrete subclasses.
from abc import ABC, abstractmethod
class MyBaseModel(SQLModel, ABC):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.custom_method()
def update(self, **kwargs):
super().update(**kwargs)
self.custom_method()
@abstractmethod
def custom_method(self):
pass
class MyModel(MyBaseModel):
def custom_method(self):
"""Do stuff here"""