Is there any way to set all methods in a class as being in an atomic transaction in Django?

Viewed 191

While using the custom action method of ViewSet in Django, I separated some business logics into another class, of which name is BusinessService.

The BusinessService class can be used from many other methods, and after some analyses, I found all methods (more than 5) in the class should be in an atomic transaction.

So the easiest but repetitive way might be adding @transaction.atomic decorator above the name of the methods, but as a way to follow the DRY principle, I was struggling to remove the redundant repetitions, but couldn't make it in a simple way.

Is there any to make a whole class in an atomic transaction?


Till now, I tried attaching @transaction.atomic above the name of a class, but, of course, had no success, so I analyzed the decorator, and found out the Atomic class which uses __enter__ and __exit__ for transaction management, which requires with or additional something.

1 Answers

You can try using a custom meta class (See What are metaclasses in Python?) which will decorate all methods of the created class. It will be something like below, (Note that there may be a few areas where this meta class can be refined):

from django.db import transaction


class AtomicTransactionMeta(type):
    def __new__(cls, name, bases, dct):
        for key, value in dct.items():
            if not key.startswith('__') and callable(value):
                # If a non-dunder method then decorate
                dct[key] = transaction.atomic(value)
        return super().__new__(cls, name, bases, dct)


class BusinessService(metaclass=AtomicTransactionMeta):
    ...
Related