diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 3e33f7867..78a3020ea 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -622,6 +622,7 @@ class ModelSerializerOptions(SerializerOptions): self.model = getattr(meta, 'model', None) self.read_only_fields = getattr(meta, 'read_only_fields', ()) self.write_only_fields = getattr(meta, 'write_only_fields', ()) + self.use_model_error_messages = getattr(meta, 'use_model_error_messages', False) class ModelSerializer(Serializer): @@ -782,7 +783,7 @@ class ModelSerializer(Serializer): "Non-existant field '%s' specified in `write_only_fields` " "on serializer '%s'." % (field_name, self.__class__.__name__)) - ret[field_name].write_only = True + ret[field_name].write_only = True return ret @@ -848,7 +849,7 @@ class ModelSerializer(Serializer): if model_field.help_text is not None: kwargs['help_text'] = model_field.help_text - if model_field.error_messages is not None: + if self.opts.use_model_error_messages and model_field.error_messages is not None: kwargs['error_messages'] = model_field.error_messages # TODO: TypedChoiceField? diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index a1e3601f9..f1bf2a72c 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -1842,35 +1842,51 @@ class BoolenFieldTypeTest(TestCase): self.assertEqual(type(bfield), fields.BooleanField) -class ErrorMessagesOnAutogeneratedFieldsTests(TestCase): +class ModelErrorMessagesFieldsTests(TestCase): def setUp(self): - class EMOAFModel(RESTFrameworkModel): + class ErrorMessageModel(RESTFrameworkModel): char_field = models.CharField(blank=False, max_length=5, error_messages={ - 'required': 'required', 'max_length': 'max_length %(limit_value)d', }) + int_field = models.IntegerField({ + 'required': 'int required model', + 'invalid': 'int invalid', + }) + + class ErrorMessageSerializer(serializers.ModelSerializer): + int_field = serializers.IntegerField(error_messages={ + 'required': 'int required', + }) - class EMOAFSerializer(serializers.ModelSerializer): class Meta: - model = EMOAFModel + model = ErrorMessageModel - self.serializer_class = EMOAFSerializer + self.serializer_class = ErrorMessageSerializer + + def error_test(self, data, expected_error_field, expected_message, enabled=False): + self.serializer_class.Meta.use_model_error_messages = enabled - def error_test(self, data, expected_message): serializer = self.serializer_class(data=data) self.assertEqual(serializer.is_valid(), False) self.assertEqual(len(serializer.errors), 1) for (field_name, message) in serializer.errors.items(): - self.assertEqual('char_field', field_name) + self.assertEqual(expected_error_field, field_name) self.assertEqual(expected_message, message[0]) - def test_required(self): - self.error_test({}, 'required') + def test_model_field_required(self): + self.error_test({'int_field': 10, 'char_field': None}, 'char_field', 'This field is required.', enabled=True) + self.error_test({'int_field': 10, 'char_field': None}, 'char_field', 'This field is required.', enabled=False) - def test_required(self): - self.error_test({'char_field': None}, 'required') + def test_model_field_validation_failure(self): + self.error_test({'int_field': 10, 'char_field': 'abcdef'}, 'char_field', 'max_length 5', enabled=True) + self.error_test({'int_field': 10, 'char_field': 'abcdef'}, 'char_field', 'Ensure this value has at most 5 characters (it has 6).', enabled=False) - def test_max_length(self): - self.error_test({'char_field': 'abcdef'}, 'max_length 5') + def test_serializer_field_required(self): + self.error_test({'char_field': 'abcde'}, 'int_field', 'int required', enabled=True) + self.error_test({'char_field': 'abcde'}, 'int_field', 'int required', enabled=False) + + def test_serializer_field_validation_failure(self): + self.error_test({'int_field': 'abc', 'char_field': 'abcde'}, 'int_field', 'Enter a whole number.', enabled=True) + self.error_test({'int_field': 'abc', 'char_field': 'abcde'}, 'int_field', 'Enter a whole number.', enabled=False)