diff options
Diffstat (limited to 'rest_framework/serializers.py')
| -rw-r--r-- | rest_framework/serializers.py | 65 | 
1 files changed, 54 insertions, 11 deletions
| diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index dfac75fc..cbac3992 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -90,12 +90,10 @@ class BaseSerializer(Field):          raise NotImplementedError('`create()` must be implemented.')      def save(self, **kwargs): -        validated_data = self.validated_data -        if kwargs: -            validated_data = dict( -                list(validated_data.items()) + -                list(kwargs.items()) -            ) +        validated_data = dict( +            list(self.validated_data.items()) + +            list(kwargs.items()) +        )          if self.instance is not None:              self.instance = self.update(self.instance, validated_data) @@ -210,9 +208,9 @@ class BoundField(object):  class NestedBoundField(BoundField):      """ -    This BoundField additionally implements __iter__ and __getitem__ +    This `BoundField` additionally implements __iter__ and __getitem__      in order to support nested bound fields. This class is the type of -    BoundField that is used for serializer fields. +    `BoundField` that is used for serializer fields.      """      def __iter__(self):          for field in self.fields.values(): @@ -460,6 +458,10 @@ class ListSerializer(BaseSerializer):      child = None      many = True +    default_error_messages = { +        'not_a_list': _('Expected a list of items but got type `{input_type}`.') +    } +      def __init__(self, *args, **kwargs):          self.child = kwargs.pop('child', copy.deepcopy(self.child))          assert self.child is not None, '`child` is a required argument.' @@ -485,7 +487,31 @@ class ListSerializer(BaseSerializer):          """          if html.is_html_input(data):              data = html.parse_html_list(data) -        return [self.child.run_validation(item) for item in data] + +        if not isinstance(data, list): +            message = self.error_messages['not_a_list'].format( +                input_type=type(data).__name__ +            ) +            raise ValidationError({ +                api_settings.NON_FIELD_ERRORS_KEY: [message] +            }) + +        ret = [] +        errors = ReturnList(serializer=self) + +        for item in data: +            try: +                validated = self.child.run_validation(item) +            except ValidationError, exc: +                errors.append(exc.detail) +            else: +                ret.append(validated) +                errors.append({}) + +        if any(errors): +            raise ValidationError(errors) + +        return ret      def to_representation(self, data):          """ @@ -497,8 +523,25 @@ class ListSerializer(BaseSerializer):              serializer=self          ) -    def create(self, attrs_list): -        return [self.child.create(attrs) for attrs in attrs_list] +    def save(self, **kwargs): +        assert self.instance is None, ( +            "Serializers do not support multiple update by default, because " +            "it would be unclear how to deal with insertions, updates and " +            "deletions. If you need to support multiple update, use a " +            "`ListSerializer` class and override `.save()` so you can specify " +            "the behavior exactly." +        ) + +        validated_data = [ +            dict(list(attrs.items()) + list(kwargs.items())) +            for attrs in self.validated_data +        ] + +        self.instance = [ +            self.child.create(attrs) for attrs in validated_data +        ] + +        return self.instance      def __repr__(self):          return representation.list_repr(self, indent=1) | 
