我最近在我的一个观看中遇到了禁用交易请求的需求,以便能够在请求期间调用db.connection.close()
和connect()
以提高性能。
我有一个DRF ViewSet,并使用以下非常简单的视图来验证non_atomic_requests decoractor似乎没有任何效果。 ATOMIC_REQUESTS=True
和settings.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。
答案 0 :(得分:5)
As documented,non_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可以在进入原子函数或块时立即启动事务。