Skip to content

Commit 0a99e02

Browse files
committed
support django 2.1 test client json data automatically serialized
1 parent 2e721cd commit 0a99e02

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

rest_framework/test.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,19 @@ def _encode_data(self, data, format=None, content_type=None):
151151
Encode the data returning a two tuple of (bytes, content_type)
152152
"""
153153

154-
if data is None:
155-
return ('', content_type)
156-
157154
assert format is None or content_type is None, (
158155
'You may not set both `format` and `content_type`.'
159156
)
160157

161158
if content_type:
159+
try:
160+
data = self._encode_json(data, content_type)
161+
except AttributeError:
162+
pass
163+
164+
if data is None:
165+
data = ''
166+
162167
# Content type specified explicitly, treat data as a raw bytestring
163168
ret = force_bytes(data, settings.DEFAULT_CHARSET)
164169

@@ -176,7 +181,6 @@ def _encode_data(self, data, format=None, content_type=None):
176181

177182
# Use format and render the data into a bytestring
178183
renderer = self.renderer_classes[format]()
179-
ret = renderer.render(data)
180184

181185
# Determine the content-type header from the renderer
182186
content_type = renderer.media_type
@@ -185,6 +189,11 @@ def _encode_data(self, data, format=None, content_type=None):
185189
content_type, renderer.charset
186190
)
187191

192+
if data is None:
193+
ret = ''
194+
else:
195+
ret = renderer.render(data)
196+
188197
# Coerce text to bytes if required.
189198
if isinstance(ret, str):
190199
ret = ret.encode(renderer.charset)

tests/test_testing.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from io import BytesIO
22

3+
from django import VERSION as DJANGO_VERSION
34
from django.contrib.auth.models import User
45
from django.shortcuts import redirect
56
from django.test import TestCase, override_settings
67
from django.urls import path
78

8-
from rest_framework import fields, serializers
9-
from rest_framework.decorators import api_view
9+
from rest_framework import fields, parsers, serializers
10+
from rest_framework.decorators import api_view, parser_classes
1011
from rest_framework.response import Response
1112
from rest_framework.test import (
1213
APIClient, APIRequestFactory, URLPatternsTestCase, force_authenticate
@@ -46,11 +47,18 @@ def post_view(request):
4647
return Response(serializer.validated_data)
4748

4849

50+
@api_view(['POST'])
51+
@parser_classes((parsers.JSONParser,))
52+
def post_json_view(request):
53+
return Response(request.data)
54+
55+
4956
urlpatterns = [
5057
path('view/', view),
5158
path('session-view/', session_view),
5259
path('redirect-view/', redirect_view),
5360
path('post-view/', post_view)
61+
path('post-json-view/', post_json_view),
5462
]
5563

5664

@@ -200,6 +208,21 @@ def test_empty_post_uses_default_boolean_value(self):
200208
assert response.status_code == 200
201209
assert response.data == {"flag": True}
202210

211+
def test_post_encodes_data_based_on_json_content_type(self):
212+
data = {'data': True}
213+
response = self.client.post(
214+
'/post-json-view/',
215+
data=data,
216+
content_type='application/json'
217+
)
218+
219+
if DJANGO_VERSION < (2, 1):
220+
assert response.status_code == 400
221+
assert response.data['detail'].code == 'parse_error'
222+
else:
223+
assert response.status_code == 200
224+
assert response.data == data
225+
203226

204227
class TestAPIRequestFactory(TestCase):
205228
def test_csrf_exempt_by_default(self):

0 commit comments

Comments
 (0)