Fix Serializer.data when provided invalid 'data' (#5646)

* Test serializer/API renderer for invalid datatype

* Fix Serializer.data with invalid input datatype
This commit is contained in:
Ryan P Kilby 2017-12-04 02:39:55 -05:00 committed by Carlton Gibson
parent b01ec450b2
commit daba5e9ba5
3 changed files with 43 additions and 0 deletions

View File

@ -398,6 +398,10 @@ class Serializer(BaseSerializer):
def get_initial(self): def get_initial(self):
if hasattr(self, 'initial_data'): if hasattr(self, 'initial_data'):
# initial_data may not be a valid type
if not isinstance(self.initial_data, Mapping):
return OrderedDict()
return OrderedDict([ return OrderedDict([
(field_name, field.get_value(self.initial_data)) (field_name, field.get_value(self.initial_data))
for field_name, field in self.fields.items() for field_name, field in self.fields.items()

View File

@ -14,6 +14,10 @@ class BasicSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class StandardPostView(generics.CreateAPIView):
serializer_class = BasicSerializer
class ManyPostView(generics.GenericAPIView): class ManyPostView(generics.GenericAPIView):
queryset = BasicModel.objects.all() queryset = BasicModel.objects.all()
serializer_class = BasicSerializer serializer_class = BasicSerializer
@ -24,6 +28,32 @@ class ManyPostView(generics.GenericAPIView):
return Response(serializer.data, status.HTTP_200_OK) return Response(serializer.data, status.HTTP_200_OK)
class TestPostingListData(TestCase):
"""
POSTing a list of data to a regular view should not cause the browsable
API to fail during rendering.
Regression test for https://github.com/encode/django-rest-framework/issues/5637
"""
def test_json_response(self):
# sanity check for non-browsable API responses
view = StandardPostView.as_view()
request = factory.post('/', [{}], format='json')
response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertTrue('non_field_errors' in response.data)
def test_browsable_api(self):
view = StandardPostView.as_view()
request = factory.post('/?format=api', [{}], format='json')
response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertTrue('non_field_errors' in response.data)
class TestManyPostView(TestCase): class TestManyPostView(TestCase):
def setUp(self): def setUp(self):
""" """

View File

@ -77,14 +77,23 @@ class TestSerializer:
serializer = self.Serializer(data={'char': 'abc', 'integer': 123}) serializer = self.Serializer(data={'char': 'abc', 'integer': 123})
assert serializer.is_valid() assert serializer.is_valid()
assert serializer.validated_data == {'char': 'abc', 'integer': 123} assert serializer.validated_data == {'char': 'abc', 'integer': 123}
assert serializer.data == {'char': 'abc', 'integer': 123}
assert serializer.errors == {} assert serializer.errors == {}
def test_invalid_serializer(self): def test_invalid_serializer(self):
serializer = self.Serializer(data={'char': 'abc'}) serializer = self.Serializer(data={'char': 'abc'})
assert not serializer.is_valid() assert not serializer.is_valid()
assert serializer.validated_data == {} assert serializer.validated_data == {}
assert serializer.data == {'char': 'abc'}
assert serializer.errors == {'integer': ['This field is required.']} assert serializer.errors == {'integer': ['This field is required.']}
def test_invalid_datatype(self):
serializer = self.Serializer(data=[{'char': 'abc'}])
assert not serializer.is_valid()
assert serializer.validated_data == {}
assert serializer.data == {}
assert serializer.errors == {'non_field_errors': ['Invalid data. Expected a dictionary, but got list.']}
def test_partial_validation(self): def test_partial_validation(self):
serializer = self.Serializer(data={'char': 'abc'}, partial=True) serializer = self.Serializer(data={'char': 'abc'}, partial=True)
assert serializer.is_valid() assert serializer.is_valid()