I recently ran into the need to disable transaction requests in one of my views, in order to be able to call db.connection.close()
and connect()
during requests in an effort to improve performance.
I have a DRF ViewSet, and used the following very simple view to verify that the non_atomic_requests decoractor seems to have no effect. ATOMIC_REQUESTS=True
is enabled in settings.py
, and 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()
After calling the view, I open Django shell, and verify that the amount of rows in the db has not grown, even though it should have. Also opening a debugger during the request to halt execution after the line m.save()
, I can observe in Django shell that a new row is not visible yet.
If I set ATOMIC_REQUESTS=False
in settings.py
, the code works as expected, and the number of rows in the db is grown by one, even if an error is raised before returning from the view.
When ATOMIC_REQUESTS=False
, using @transaction.atomic
decorator does work as expected though. So as a workaround, I could use it to set every other view as atomic instead...
I am currently thinking this is a bug in the framework. Can anybody verify my findings, or point out if I am misunderstanding how this decorator is meant to function?
I am using Python 3.6, Django 2.0 and DRF 3.7.7.
As documented, non_atomic_requests
only works if it's applied to the view itself.
In your case, create
is a viewset method, it is not the view itself. With a regular class based view in Django, you'd need to wrap the dispatch
method using method_decorator
.
@method_decorator(transaction.non_atomic_requests, name='dispatch')
class MyViewSet(ViewSet):
...
def create(self, *args, **kwargs):
...
I'm not familiar enough with the rest framework internals to say whether this will work or not. Note that it will disable atomic requests for all views handled by the viewset, not just the create
method.
The non_atomic_requests
method has this limitation because the Django request handler has to inspect the view before it runs so that it knows whether to run it in a transaction. The transaction.atomic
decorator does not have the same requirement - Django can simply start the transaction as soon as it enters an atomic function or block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With