Python/SQLModel; nice syntax to add a method call to `__init__` and `update`?

91 Views Asked by At

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?

1

There are 1 best solutions below

2
chepner On BEST ANSWER

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"""