Django decorator @ transaction.non_atomic_requests无法在ViewSet方法

时间:2018-04-18 15:04:49

标签: python django transactions django-rest-framework

我最近在我的一个观看中遇到了禁用交易请求的需求,以便能够在请求期间调用db.connection.close()connect()以提高性能。

我有一个DRF ViewSet,并使用以下非常简单的视图来验证non_atomic_requests decoractor似乎没有任何效果。 ATOMIC_REQUESTS=Truesettings.py已启用DEBUG=False

from django.db import transaction    

@transaction.non_atomic_requests
def create(self, *args, **kwargs):
    m = MyModel(stuff="hello")
    m.save()
    raise Exception('exception! row should still be saved though')
    return Response()

在调用视图之后,我打开Django shell,并验证db中的行数没有增长,即使它应该有。在请求停止执行行m.save()之后也打开一个调试器,我可以在Django shell中观察到还没有看到新行。

如果我在ATOMIC_REQUESTS=False中设置settings.py,则代码按预期工作,并且db中的行数增加1,即使从视图返回之前引发了错误。< / p>

ATOMIC_REQUESTS=False时,使用@transaction.atomic装饰器确实可以正常工作。因此,作为一种解决方法,我可以使用它将每个其他视图设置为原子而不是......

我目前认为这是框架中的一个错误。任何人都可以验证我的发现,或者指出我是否误解了这个装饰器的功能是什么?

我正在使用Python 3.6,Django 2.0和DRF 3.7.7。

1 个答案:

答案 0 :(得分:5)

As documentednon_atomic_requests仅在应用于视图本身时才有效。

在您的情况下,create是一个viewset方法,它不是视图本身。在Django中使用常规的基于类的视图,您需要使用method_decorator包装dispatch方法。

@method_decorator(transaction.non_atomic_requests, name='dispatch') 
class MyViewSet(ViewSet):
    ...

    def create(self, *args, **kwargs):
        ...

我对其余的框架内部结构不够熟悉,不知道这是否有效。请注意,它将禁用视图集处理的所有视图的原子请求,而不仅仅是create方法。

non_atomic_requests方法具有此限制,因为Django请求处理程序必须在视图运行之前检查该视图,以便它知道是否在事务中运行它。 transaction.atomic装饰器没有相同的要求 - Django可以在进入原子函数或块时立即启动事务。