8000 support django 2.1 test client json data automatically serialized · encode/django-rest-framework@4579eae · GitHub
[go: up one dir, main page]

Skip to content

Commit 4579eae

Browse files
committed
support django 2.1 test client json data automatically serialized
1 parent a8595a8 commit 4579eae

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

docs/api-guide/testing.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ The `APIRequestFactory` class supports an almost identical API to Django's stand
2525
factory = APIRequestFactory()
2626
request = factory.post('/notes/', {'title': 'new idea'})
2727

28+
# Using the standard RequestFactory API to encode JSON data
29+
request = factory.post('/notes/', {'title': 'new idea'}, content_type='application/json')
30+
2831
#### Using the `format` argument
2932

30-
Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a content type other than multipart form data. For example:
33+
Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a wide set of request formats. When using this argument, the factory will select an appropriate renderer and its configured `content_type`. For example:
3134

3235
# Create a JSON POST request
3336
factory = APIRequestFactory()
@@ -41,7 +44,7 @@ To support a wider set of request formats, or change the default format, [see th
4144

4245
If you need to explicitly encode the request body, you can do so by setting the `content_type` flag. For example:
4346

44-
request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')
47+
request = factory.post('/notes/', yaml.dump({'title': 'new idea'}), content_type='application/yaml')
4548

4649
#### PUT and PATCH with form data
4750

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: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
from django.test import TestCase, override_settings
99
from django.urls import path
1010

11-
from rest_framework import fields, serializers
11+
from rest_framework import fields, parsers, serializers
1212
from rest_framework.authtoken.models import Token
13-
from rest_framework.decorators import api_view
13+
from rest_framework.decorators import api_view, parser_classes
1414
from rest_framework.response import Response
1515
from rest_framework.test import (
1616
APIClient, APIRequestFactory, URLPatternsTestCase, force_authenticate
@@ -50,6 +50,12 @@ class BasicSerializer(serializers.Serializer):
5050
flag = fields.BooleanField(default=lambda: True)
5151

5252

53+
@api_view(['POST'])
54+
@parser_classes((parsers.JSONParser,))
55+
def post_json_view(request):
56+
return Response(request.data)
57+
58+
5359
@api_view(['POST'])
5460
def post_view(request):
5561
serializer = BasicSerializer(data=request.data)
@@ -62,7 +68,8 @@ def post_view(request):
6268
path('session-view/', session_view),
6369
path('redirect-view/', redirect_view),
6470
path('redirect-view/<int:code>/', redirect_307_308_view),
65-
path('post-view/', post_view)
71+
path('post-json-view/', post_json_view),
72+
path('post-view/', post_view),
6673
]
6774

6875

@@ -236,6 +243,17 @@ def test_empty_post_uses_default_boolean_value(self):
236243
assert response.status_code == 200
237244
assert response.data == {"flag": True}
238245

246+
def test_post_encodes_data_based_on_json_content_type(self):
247+
data = {'data': True}
248+
response = self.client.post(
249+
'/post-json-view/',
250+
data=data,
251+
content_type='application/json'
252+
)
253+
254+
assert response.status_code == 200
255+
assert response.data == data
256+
239257

240258
class TestAPIRequestFactory(TestCase):
241259
def test_csrf_exempt_by_default(self):

0 commit comments

Comments
 (0)
0