Django REST Framework 故意引发错误时的事务错误

Transaction error when Django REST Framework raises an error on purpose

我已经将使用 Django REST Framework 的项目从 2.x 版本更新到最新的稳定版本 (3.1.3)。在我的序列化程序中修复了一些不推荐使用的用途后,我 运行 python manage.py test 以确保没有任何问题。

除了我测试无效 REST 请求(故意)的一些测试外,一切正常。例如:

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)

视图集生成一个类似 MyEventModel.objects.get(user=request.user, pk=123) 的 ORM 查询,这显然会在 DRF 中引发 404 异常,因为这里不应返回任何对象 (我知道,它应该是 403 才能符合 REST...)。但这引发了 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.

看起来我的一个中间件在查看后执行一些 SQL 查询,然后点击 transaction closed by DRF, since the 3.1.3。所需的行为(即获得 404 NOT FOUND)适用于 3.1.2...

有人知道如何避免回滚吗?是不是对DRF的误解?

这看起来像是 DRF 中的一个错误,已被修复。如您所见,here 他们更改了代码,使其仅在原子块中回滚。

由于没有发布更新的版本,您可以对已安装的代码应用相同的修复程序,也可以使用较早的版本,直到 3.1.3 被取代。