【问题标题】:Is there any way to set all methods in a class as being in an atomic transaction in Django?有没有办法将类中的所有方法设置为 Django 中的原子事务?
【发布时间】:2021-05-14 12:05:10
【问题描述】:

在 Django 中使用 ViewSet 的自定义操作方法时,我将一些业务逻辑分离到另一个类中,其名称为BusinessService

BusinessService 类可以从许多其他方法中使用,经过一些分析,我发现该类中的所有方法(超过 5 个)都应该在一个原子事务中。

因此,最简单但重复的方法可能是在方法名称上方添加 @transaction.atomic 装饰器,但作为遵循 the DRY principle 的一种方式,我正在努力删除多余的重复,但无法在简单的方法。

有没有什么可以在原子事务中创建一个完整的类?


到目前为止,我尝试在类名上方附加@transaction.atomic,当然没有成功,所以我分析了装饰器,发现Atomic类使用了__enter__和@987654328 @ 用于事务管理,需要with 或其他东西。

【问题讨论】:

    标签: python django transactions


    【解决方案1】:

    您可以尝试使用自定义元类(请参阅What are metaclasses in Python?),它将装饰已创建类的所有方法。如下所示,(请注意,这个元类可能有一些地方可以细化):

    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):
        ...
    

    【讨论】:

    • 天哪,我真的很感谢你,@abdul-aziz-barkat!!!我不知道元类可以这样使用。我去试试!
    • 我在这里找到了另一种方法! :stackoverflow.com/a/64988399/15555320 ---- 上面的答案在性能方面可能有点低效,因为它遍历所有方法并添加装饰器逻辑,而不是直接将逻辑添加到被调用的方法中。 ---- 然而,就逻辑的范围而言,上面的答案是完全准确的,因为它与原始装饰器在相同的范围内工作,但用with 覆盖 call 方法似乎在某种程度上扩展了范围到覆盖逻辑的末尾,因此不会在方法结束后立即插入数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2023-03-27
    相关资源
    最近更新 更多