I have updated a project using Django REST Framework from a 2.x version to the last stable version (3.1.3). After fixing some deprecated uses in my serializers, I ran python manage.py test
to make sure nothing have been broken.
Everything works fine except some of my tests where I am testing invalid REST requests (on purpose). For example:
def test_get_events_of_other_user(self):
# Assume the setUp log the user1 with self.client
# and here, there is some code initializing an
# event for user2
response = self.client.get("/event/123/")
self.assertEqual(404, response.status_code)
The viewset generate a ORM-query like MyEventModel.objects.get(user=request.user, pk=123)
, which obviously raises a 404 exception in DRF, since no object should be returned here (I know, it should be a 403 to be REST-compliant...). But this raises a TransactionManagementError
:
Traceback (most recent call last):
[...]
File "/my_virtual_env_path/local/lib/python2.7/site-packages/rest_framework/viewsets.py", line 85, in view
return self.dispatch(request, *args, **kwargs)
File "/my_virtual_env_path/local/lib/python2.7/site-packages/rest_framework/views.py", line 456, in dispatch
response = self.handle_exception(exc)
File "/my_virtual_env_path/local/lib/python2.7/site-packages/rest_framework/views.py", line 421, in handle_exception
response = exception_handler(exc, context)
File "/my_virtual_env_path/local/lib/python2.7/site-packages/rest_framework/views.py", line 81, in exception_handler
set_rollback()
File "/my_virtual_env_path/local/lib/python2.7/site-packages/rest_framework/compat.py", line 277, in set_rollback
transaction.set_rollback(True)
File "/my_virtual_env_path/local/lib/python2.7/site-packages/django/db/transaction.py", line 215, in set_rollback
return get_connection(using).set_rollback(rollback)
File "/my_virtual_env_path/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 372, in set_rollback
"The rollback flag doesn't work outside of an 'atomic' block.")
TransactionManagementError: The rollback flag doesn't work outside of an 'atomic' block.
It looks like one of my middleware is doing some SQL query after the view, and hit the transaction closed by DRF, since the 3.1.3. The desired behaviour (i.e get a 404 NOT FOUND) works with the 3.1.2...
Does anyone has an idea of how I could avoid the rollback? Is it a misconception in DRF?