From 345bf42ce989b2361ad90617130b82c53d7fbb03 Mon Sep 17 00:00:00 2001 From: Ian Foote Date: Sun, 7 Dec 2014 11:59:08 +0000 Subject: [PATCH] Add validate method back to ListSerializer --- rest_framework/serializers.py | 36 ++++++++++++++++++++++++++++++++++ tests/test_serializer_lists.py | 16 +++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index d8e544d471..c8f02d8a2c 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -462,6 +462,42 @@ def get_value(self, dictionary): return html.parse_html_list(dictionary, prefix=self.field_name) return dictionary.get(self.field_name, empty) + def run_validation(self, data=empty): + data = super(ListSerializer, self).run_validation(data) + + try: + data = self.validate(data) + assert data is not None, '.validate() should return the validated data' + except ValidationError as exc: + if isinstance(exc.detail, dict): + # .validate() errors may be a dict, in which case, use + # standard {key: list of values} style. + raise ValidationError(dict([ + (key, value if isinstance(value, list) else [value]) + for key, value in exc.detail.items() + ])) + elif isinstance(exc.detail, list): + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: exc.detail + }) + else: + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [exc.detail] + }) + except DjangoValidationError as exc: + # Normally you should raise `serializers.ValidationError` + # inside your codebase, but we handle Django's validation + # exception class as well for simpler compat. + # Eg. Calling Model.clean() explicitly inside Serializer.validate() + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: list(exc.messages) + }) + + return data + + def validate(self, attrs): + return attrs + def to_internal_value(self, data): """ List of dicts of native values <- List of dicts of primitive datatypes. diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 640067e3a6..35b68ae7de 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -272,3 +272,19 @@ def test_validate_html_input(self): serializer = self.Serializer(data=input_data) assert serializer.is_valid() assert serializer.validated_data == expected_output + + +class TestListSerializerClass: + """Tests for a custom list_serializer_class.""" + def test_list_serializer_class_validate(self): + class CustomListSerializer(serializers.ListSerializer): + def validate(self, attrs): + raise serializers.ValidationError('Non field error') + + class TestSerializer(serializers.Serializer): + class Meta: + list_serializer_class = CustomListSerializer + + serializer = TestSerializer(data=[], many=True) + assert not serializer.is_valid() + assert serializer.errors == {'non_field_errors': ['Non field error']}