Skip to content

Commit daba5e9

Browse files
Ryan P Kilbycarltongibson
authored andcommitted
Fix Serializer.data when provided invalid 'data' (#5646)
* Test serializer/API renderer for invalid datatype * Fix Serializer.data with invalid input datatype
1 parent b01ec45 commit daba5e9

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

rest_framework/serializers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,10 @@ def get_validators(self):
398398

399399
def get_initial(self):
400400
if hasattr(self, 'initial_data'):
401+
# initial_data may not be a valid type
402+
if not isinstance(self.initial_data, Mapping):
403+
return OrderedDict()
404+
401405
return OrderedDict([
402406
(field_name, field.get_value(self.initial_data))
403407
for field_name, field in self.fields.items()

tests/browsable_api/test_form_rendering.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class Meta:
1414
fields = '__all__'
1515

1616

17+
class StandardPostView(generics.CreateAPIView):
18+
serializer_class = BasicSerializer
19+
20+
1721
class ManyPostView(generics.GenericAPIView):
1822
queryset = BasicModel.objects.all()
1923
serializer_class = BasicSerializer
@@ -24,6 +28,32 @@ def post(self, request, *args, **kwargs):
2428
return Response(serializer.data, status.HTTP_200_OK)
2529

2630

31+
class TestPostingListData(TestCase):
32+
"""
33+
POSTing a list of data to a regular view should not cause the browsable
34+
API to fail during rendering.
35+
36+
Regression test for https://github.com/encode/django-rest-framework/issues/5637
37+
"""
38+
39+
def test_json_response(self):
40+
# sanity check for non-browsable API responses
41+
view = StandardPostView.as_view()
42+
request = factory.post('/', [{}], format='json')
43+
response = view(request).render()
44+
45+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
46+
self.assertTrue('non_field_errors' in response.data)
47+
48+
def test_browsable_api(self):
49+
view = StandardPostView.as_view()
50+
request = factory.post('/?format=api', [{}], format='json')
51+
response = view(request).render()
52+
53+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
54+
self.assertTrue('non_field_errors' in response.data)
55+
56+
2757
class TestManyPostView(TestCase):
2858
def setUp(self):
2959
"""

tests/test_serializer.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,23 @@ def test_valid_serializer(self):
7777
serializer = self.Serializer(data={'char': 'abc', 'integer': 123})
7878
assert serializer.is_valid()
7979
assert serializer.validated_data == {'char': 'abc', 'integer': 123}
80+
assert serializer.data == {'char': 'abc', 'integer': 123}
8081
assert serializer.errors == {}
8182

8283
def test_invalid_serializer(self):
8384
serializer = self.Serializer(data={'char': 'abc'})
8485
assert not serializer.is_valid()
8586
assert serializer.validated_data == {}
87+
assert serializer.data == {'char': 'abc'}
8688
assert serializer.errors == {'integer': ['This field is required.']}
8789

90+
def test_invalid_datatype(self):
91+
serializer = self.Serializer(data=[{'char': 'abc'}])
92+
assert not serializer.is_valid()
93+
assert serializer.validated_data == {}
94+
assert serializer.data == {}
95+
assert serializer.errors == {'non_field_errors': ['Invalid data. Expected a dictionary, but got list.']}
96+
8897
def test_partial_validation(self):
8998
serializer = self.Serializer(data={'char': 'abc'}, partial=True)
9099
assert serializer.is_valid()

0 commit comments

Comments
 (0)