mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-04 12:30:11 +03:00
If required=False custom validation shouldn't be triggered
For optional fields (`required=False`), custom validation (`validate_<fieldname>()`) should only be called if the field is present in the incoming data.
This commit is contained in:
parent
27af7a3f4f
commit
86b7940d56
|
@ -286,6 +286,12 @@ class BaseSerializer(WritableField):
|
|||
|
||||
return reverted_data
|
||||
|
||||
def skip_field_validation(self, field, attrs, source):
|
||||
"""
|
||||
Checks if a field validation should be skipped.
|
||||
"""
|
||||
return source not in attrs and (field.partial or not field.required)
|
||||
|
||||
def perform_validation(self, attrs):
|
||||
"""
|
||||
Run `validate_<fieldname>()` and `validate()` methods on the serializer
|
||||
|
@ -295,8 +301,9 @@ class BaseSerializer(WritableField):
|
|||
continue
|
||||
|
||||
source = field.source or field_name
|
||||
if self.partial and source not in attrs:
|
||||
if self.skip_field_validation(field_name, field, attrs):
|
||||
continue
|
||||
|
||||
try:
|
||||
validate_method = getattr(self, 'validate_%s' % field_name, None)
|
||||
if validate_method:
|
||||
|
|
|
@ -562,6 +562,7 @@ class ValidationTests(TestCase):
|
|||
|
||||
class CustomValidationTests(TestCase):
|
||||
class CommentSerializerWithFieldValidator(CommentSerializer):
|
||||
name = serializers.CharField(max_length=255, required=False)
|
||||
|
||||
def validate_email(self, attrs, source):
|
||||
attrs[source]
|
||||
|
@ -573,6 +574,12 @@ class CustomValidationTests(TestCase):
|
|||
raise serializers.ValidationError("Test not in value")
|
||||
return attrs
|
||||
|
||||
def validate_name(self, attrs, source):
|
||||
value = attrs[source]
|
||||
if value.isupper():
|
||||
raise serializers.ValidationError("Uppercase names not allowed")
|
||||
return attrs
|
||||
|
||||
def test_field_validation(self):
|
||||
data = {
|
||||
'email': 'tom@example.com',
|
||||
|
@ -601,6 +608,35 @@ class CustomValidationTests(TestCase):
|
|||
self.assertFalse(serializer.is_valid())
|
||||
self.assertEqual(serializer.errors, {'content': ['This field is required.']})
|
||||
|
||||
def test_not_required_missing_data(self):
|
||||
"""
|
||||
Make sure that `validate_<fieldname>()` is not called if the field is not required and
|
||||
the field is missing.
|
||||
"""
|
||||
data = {
|
||||
'email': 'tom@example.com',
|
||||
'content': 'A test comment',
|
||||
'created': datetime.datetime(2012, 1, 1)
|
||||
}
|
||||
serializer = self.CommentSerializerWithFieldValidator(data=data)
|
||||
self.assertTrue(serializer.is_valid())
|
||||
self.assertEqual(serializer.errors, {'content': ['This field is required.']})
|
||||
|
||||
def test_not_required_invalid_data(self):
|
||||
"""
|
||||
Make sure that `validate_<fieldname>()` is called if the field is present, even if the
|
||||
field is not required.
|
||||
"""
|
||||
data = {
|
||||
'name': 'TOM',
|
||||
'email': 'tom@example.com',
|
||||
'content': 'A test comment',
|
||||
'created': datetime.datetime(2012, 1, 1)
|
||||
}
|
||||
serializer = self.CommentSerializerWithFieldValidator(data=data)
|
||||
self.assertFalse(serializer.is_valid())
|
||||
self.assertEqual(serializer.errors, {'name': ['Uppercase names not allowed']})
|
||||
|
||||
def test_wrong_data(self):
|
||||
"""
|
||||
Make sure that validate_content isn't called if the field input is wrong
|
||||
|
|
Loading…
Reference in New Issue
Block a user