I am using Django Rest Framework and its class-based view, with database connection set to ATOMIC_REQUESTS=True.
To optimize the application, I would like to have it so that only PUT and POST requests are under transaction, but not GET. Since I have ATOMIC_REQUESTS on, the documentation says to use the decorator on the dispatch() method in the view. So this is what I tried:
class MyView(APIView):
def get():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def post():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def put():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def dispatch(self, request, *args, **kwargs):
"""Override dispatch method and selectively apply non_atomic_requests"""
if request.method.lower() == "get":
return self.non_atomic_dispatch(request, *args, **kwargs)
else:
return super().dispatch(request, *args, **kwargs)
@transaction.non_atomic_requests
def non_atomic_dispatch(self, request, *args, **kwargs):
"""Special dispatch method decorated with non_atomic_requests"""
return super().dispatch(request, *args, **kwargs)
This does not work, since the get method still reports itself as under transaction, however, if I switch the decorator to look like this:
...
@transaction.non_atomic_requests
def dispatch(self, request, *args, **kwargs):
if request.method.lower() == "get":
return self.non_atomic_dispatch(request, *args, **kwargs)
else:
return super().dispatch(request, *args, **kwargs)
def non_atomic_dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
...
This works, though obviously it's not what I want.
My questions are:
Why does the placement of the decorator matter, if I am merely returning the same thing?
How do I make this work the way I want?