mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-10 19:56:59 +03:00
support multi db atomic_requests (#7739)
This commit is contained in:
parent
8f6d2d2f9c
commit
de7468d0b4
|
@ -3,7 +3,7 @@ Provides an APIView class that is the base of all views in REST framework.
|
|||
"""
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import connection, models, transaction
|
||||
from django.db import connections, models
|
||||
from django.http import Http404
|
||||
from django.http.response import HttpResponseBase
|
||||
from django.utils.cache import cc_delim_re, patch_vary_headers
|
||||
|
@ -63,9 +63,9 @@ def get_view_description(view, html=False):
|
|||
|
||||
|
||||
def set_rollback():
|
||||
atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False)
|
||||
if atomic_requests and connection.in_atomic_block:
|
||||
transaction.set_rollback(True)
|
||||
for db in connections.all():
|
||||
if db.settings_dict['ATOMIC_REQUESTS'] and db.in_atomic_block:
|
||||
db.set_rollback(True)
|
||||
|
||||
|
||||
def exception_handler(exc, context):
|
||||
|
|
|
@ -24,6 +24,10 @@ def pytest_configure(config):
|
|||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:'
|
||||
},
|
||||
'secondary': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:'
|
||||
}
|
||||
},
|
||||
SITE_ID=1,
|
||||
|
|
|
@ -130,6 +130,41 @@ class DBTransactionAPIExceptionTests(TestCase):
|
|||
assert BasicModel.objects.count() == 0
|
||||
|
||||
|
||||
@unittest.skipUnless(
|
||||
connection.features.uses_savepoints,
|
||||
"'atomic' requires transactions and savepoints."
|
||||
)
|
||||
class MultiDBTransactionAPIExceptionTests(TestCase):
|
||||
databases = '__all__'
|
||||
|
||||
def setUp(self):
|
||||
self.view = APIExceptionView.as_view()
|
||||
connections.databases['default']['ATOMIC_REQUESTS'] = True
|
||||
connections.databases['secondary']['ATOMIC_REQUESTS'] = True
|
||||
|
||||
def tearDown(self):
|
||||
connections.databases['default']['ATOMIC_REQUESTS'] = False
|
||||
connections.databases['secondary']['ATOMIC_REQUESTS'] = False
|
||||
|
||||
def test_api_exception_rollback_transaction(self):
|
||||
"""
|
||||
Transaction is rollbacked by our transaction atomic block.
|
||||
"""
|
||||
request = factory.post('/')
|
||||
num_queries = 4 if connection.features.can_release_savepoints else 3
|
||||
with self.assertNumQueries(num_queries):
|
||||
# 1 - begin savepoint
|
||||
# 2 - insert
|
||||
# 3 - rollback savepoint
|
||||
# 4 - release savepoint
|
||||
with transaction.atomic(), transaction.atomic(using='secondary'):
|
||||
response = self.view(request)
|
||||
assert transaction.get_rollback()
|
||||
assert transaction.get_rollback(using='secondary')
|
||||
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
assert BasicModel.objects.count() == 0
|
||||
|
||||
|
||||
@unittest.skipUnless(
|
||||
connection.features.uses_savepoints,
|
||||
"'atomic' requires transactions and savepoints."
|
||||
|
|
Loading…
Reference in New Issue
Block a user