diff options
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/serializers.py | 23 | ||||
| -rw-r--r-- | rest_framework/tests/serializer.py | 40 |
2 files changed, 51 insertions, 12 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index ba9e9e9c..106e3f17 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -7,8 +7,7 @@ from django.core.paginator import Page from django.db import models from django.forms import widgets from django.utils.datastructures import SortedDict -from rest_framework.compat import get_concrete_model -from rest_framework.compat import six +from rest_framework.compat import get_concrete_model, six # Note: We do the following so that users of the framework can use this style: # @@ -285,10 +284,6 @@ class BaseSerializer(Field): """ Deserialize primitives -> objects. """ - if hasattr(data, '__iter__') and not isinstance(data, (dict, six.text_type)): - # TODO: error data when deserializing lists - return [self.from_native(item, None) for item in data] - self._errors = {} if data is not None or files is not None: attrs = self.restore_fields(data, files) @@ -330,7 +325,7 @@ class BaseSerializer(Field): if self.many is not None: many = self.many else: - many = hasattr(obj, '__iter__') and not isinstance(obj, (Page, dict)) + many = hasattr(obj, '__iter__') and not isinstance(obj, (Page, dict, six.text_type)) if many: return [self.to_native(item) for item in obj] @@ -348,19 +343,25 @@ class BaseSerializer(Field): if self.many is not None: many = self.many else: - many = hasattr(data, '__iter__') and not isinstance(data, (Page, dict)) + many = hasattr(data, '__iter__') and not isinstance(data, (Page, dict, six.text_type)) if many: warnings.warn('Implict list/queryset serialization is due to be deprecated. ' 'Use the `many=True` flag when instantiating the serializer.', PendingDeprecationWarning, stacklevel=3) - # TODO: error data when deserializing lists if many: - ret = [self.from_native(item, None) for item in data] - ret = self.from_native(data, files) + ret = [] + errors = [] + for item in data: + ret.append(self.from_native(item, None)) + errors.append(self._errors) + self._errors = any(errors) and errors or [] + else: + ret = self.from_native(data, files) if not self._errors: self.object = ret + return self._errors def is_valid(self): diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 51065017..beb372c2 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -268,7 +268,16 @@ class ValidationTests(TestCase): data = ['i am', 'a', 'list'] serializer = CommentSerializer(self.comment, data=data, many=True) self.assertEqual(serializer.is_valid(), False) - self.assertEqual(serializer.errors, {'non_field_errors': ['Invalid data']}) + self.assertTrue(isinstance(serializer.errors, list)) + + self.assertEqual( + serializer.errors, + [ + {'non_field_errors': ['Invalid data']}, + {'non_field_errors': ['Invalid data']}, + {'non_field_errors': ['Invalid data']} + ] + ) data = 'and i am a string' serializer = CommentSerializer(self.comment, data=data) @@ -1072,3 +1081,32 @@ class NestedSerializerContextTests(TestCase): # This will raise RuntimeError if context doesn't get passed correctly to the nested Serializers AlbumCollectionSerializer(album_collection, context={'context_item': 'album context'}).data + + +class DeserializeListTestCase(TestCase): + + def setUp(self): + self.data = { + 'email': 'nobody@nowhere.com', + 'content': 'This is some test content', + 'created': datetime.datetime(2013, 3, 7), + } + + def test_no_errors(self): + data = [self.data.copy() for x in range(0, 3)] + serializer = CommentSerializer(data=data) + self.assertTrue(serializer.is_valid()) + self.assertTrue(isinstance(serializer.object, list)) + self.assertTrue( + all((isinstance(item, Comment) for item in serializer.object)) + ) + + def test_errors_return_as_list(self): + invalid_item = self.data.copy() + invalid_item['email'] = '' + data = [self.data.copy(), invalid_item, self.data.copy()] + + serializer = CommentSerializer(data=data) + self.assertFalse(serializer.is_valid()) + expected = [{}, {'email': ['This field is required.']}, {}] + self.assertEqual(serializer.errors, expected) |
