Skip to content

Commit b06f944

Browse files
committed
Merge pull request #3016 from hellysmile/non_atomic_requests
Fix set_rollback on @transaction.non_atomic_requests.
2 parents ca0a7ee + cbfce93 commit b06f944

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

rest_framework/compat.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ def set_rollback():
274274
if connection.settings_dict.get('ATOMIC_REQUESTS', False):
275275
# If running in >=1.6 then mark a rollback as required,
276276
# and allow it to be handled by Django.
277-
transaction.set_rollback(True)
277+
if connection.in_atomic_block:
278+
transaction.set_rollback(True)
278279
elif transaction.is_managed():
279280
# Otherwise handle it explicitly if in managed mode.
280281
if transaction.is_dirty():

tests/test_atomic_requests.py

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from __future__ import unicode_literals
22

3+
from django.conf.urls import patterns, url
34
from django.db import connection, connections, transaction
4-
from django.test import TestCase
5+
from django.test import TestCase, TransactionTestCase
6+
from django.http import Http404
7+
from django.utils.decorators import method_decorator
58
from django.utils.unittest import skipUnless
69
from rest_framework import status
710
from rest_framework.exceptions import APIException
@@ -108,3 +111,37 @@ def test_api_exception_rollback_transaction(self):
108111
self.assertEqual(response.status_code,
109112
status.HTTP_500_INTERNAL_SERVER_ERROR)
110113
assert BasicModel.objects.count() == 0
114+
115+
116+
@skipUnless(connection.features.uses_savepoints,
117+
"'atomic' requires transactions and savepoints.")
118+
class NonAtomicDBTransactionAPIExceptionTests(TransactionTestCase):
119+
@property
120+
def urls(self):
121+
class NonAtomicAPIExceptionView(APIView):
122+
@method_decorator(transaction.non_atomic_requests)
123+
def dispatch(self, *args, **kwargs):
124+
return super(NonAtomicAPIExceptionView, self).dispatch(*args, **kwargs)
125+
126+
def get(self, request, *args, **kwargs):
127+
BasicModel.objects.all()
128+
raise Http404
129+
130+
return patterns(
131+
'',
132+
url(r'^$', NonAtomicAPIExceptionView.as_view())
133+
)
134+
135+
def setUp(self):
136+
connections.databases['default']['ATOMIC_REQUESTS'] = True
137+
138+
def tearDown(self):
139+
connections.databases['default']['ATOMIC_REQUESTS'] = False
140+
141+
def test_api_exception_rollback_transaction_non_atomic_view(self):
142+
response = self.client.get('/')
143+
144+
# without checking connection.in_atomic_block view raises 500
145+
# due attempt to rollback without transaction
146+
self.assertEqual(response.status_code,
147+
status.HTTP_404_NOT_FOUND)

0 commit comments

Comments
 (0)