Skip to content

Commit 466426e

Browse files
committed
Improve reason_phrase for error details that are length 1 lists.
1 parent bce86c7 commit 466426e

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

rest_framework/views.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def exception_handler(exc, context):
9797
else:
9898
data = {"detail": exc.detail}
9999
reason = str(exc.detail)
100+
if isinstance(exc.detail, list) and len(exc.detail) == 1:
101+
reason = exc.detail[0]
100102

101103
set_rollback()
102104
return Response(data, status=exc.status_code, headers=headers, reason=reason)

tests/test_views.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from rest_framework import status
77
from rest_framework.decorators import api_view
8+
from rest_framework.exceptions import ValidationError
89
from rest_framework.response import Response
910
from rest_framework.settings import APISettings, api_settings
1011
from rest_framework.test import APIRequestFactory
@@ -15,6 +16,7 @@
1516
JSON_ERROR = 'JSON parse error - Expecting value:'
1617
STATUS_CODE_400 = 'Bad Request'
1718
REASON_PHRASE_RE = fr"{STATUS_CODE_400} \({JSON_ERROR}.*\)"
19+
VALIDATION_ERROR = "Data isn't valid!"
1820

1921

2022
class BasicView(APIView):
@@ -42,6 +44,11 @@ def get(self, request, *args, **kwargs):
4244
raise Exception
4345

4446

47+
class ValidationErrorView(APIView):
48+
def get(self, request, *args, **kwargs):
49+
raise ValidationError(VALIDATION_ERROR)
50+
51+
4552
def custom_handler(exc, context):
4653
if isinstance(exc, SyntaxError):
4754
return Response({'error': 'SyntaxError'}, status=400)
@@ -60,6 +67,11 @@ def error_view(request):
6067
raise Exception
6168

6269

70+
@api_view(['GET'])
71+
def validation_error_view(request):
72+
raise ValidationError(VALIDATION_ERROR)
73+
74+
6375
def sanitise_json_error(error_dict):
6476
"""
6577
Exact contents of JSON error messages depend on the installed version
@@ -72,34 +84,44 @@ def sanitise_json_error(error_dict):
7284

7385

7486
class ClassBasedViewIntegrationTests(TestCase):
75-
def setUp(self):
76-
self.view = BasicView.as_view()
7787

7888
def test_400_parse_error(self):
7989
request = factory.post('/', 'f00bar', content_type='application/json')
80-
response = self.view(request)
90+
response = BasicView.as_view()(request)
8191
expected = {
8292
'detail': JSON_ERROR
8393
}
8494
assert response.status_code == status.HTTP_400_BAD_REQUEST
8595
assert re.match(REASON_PHRASE_RE, response.reason_phrase)
8696
assert sanitise_json_error(response.data) == expected
8797

98+
def test_400_validation_error(self):
99+
request = factory.get('/')
100+
response = ValidationErrorView.as_view()(request)
101+
assert response.status_code == status.HTTP_400_BAD_REQUEST
102+
assert response.reason_phrase == f"{STATUS_CODE_400} ({VALIDATION_ERROR})"
103+
assert response.data == [VALIDATION_ERROR]
104+
88105

89106
class FunctionBasedViewIntegrationTests(TestCase):
90-
def setUp(self):
91-
self.view = basic_view
92107

93108
def test_400_parse_error(self):
94109
request = factory.post('/', 'f00bar', content_type='application/json')
95-
response = self.view(request)
110+
response = basic_view(request)
96111
expected = {
97112
'detail': JSON_ERROR
98113
}
99114
assert response.status_code == status.HTTP_400_BAD_REQUEST
100115
assert re.match(REASON_PHRASE_RE, response.reason_phrase)
101116
assert sanitise_json_error(response.data) == expected
102117

118+
def test_400_validation_error(self):
119+
request = factory.get('/')
120+
response = validation_error_view(request)
121+
assert response.status_code == status.HTTP_400_BAD_REQUEST
122+
assert response.reason_phrase == f"{STATUS_CODE_400} ({VALIDATION_ERROR})"
123+
assert response.data == [VALIDATION_ERROR]
124+
103125

104126
class TestCustomExceptionHandler(TestCase):
105127
def setUp(self):

0 commit comments

Comments
 (0)