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
|
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):
|
def perform_validation(self, attrs):
|
||||||
"""
|
"""
|
||||||
Run `validate_<fieldname>()` and `validate()` methods on the serializer
|
Run `validate_<fieldname>()` and `validate()` methods on the serializer
|
||||||
|
@ -295,8 +301,9 @@ class BaseSerializer(WritableField):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
source = field.source or field_name
|
source = field.source or field_name
|
||||||
if self.partial and source not in attrs:
|
if self.skip_field_validation(field_name, field, attrs):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
validate_method = getattr(self, 'validate_%s' % field_name, None)
|
validate_method = getattr(self, 'validate_%s' % field_name, None)
|
||||||
if validate_method:
|
if validate_method:
|
||||||
|
|
|
@ -562,6 +562,7 @@ class ValidationTests(TestCase):
|
||||||
|
|
||||||
class CustomValidationTests(TestCase):
|
class CustomValidationTests(TestCase):
|
||||||
class CommentSerializerWithFieldValidator(CommentSerializer):
|
class CommentSerializerWithFieldValidator(CommentSerializer):
|
||||||
|
name = serializers.CharField(max_length=255, required=False)
|
||||||
|
|
||||||
def validate_email(self, attrs, source):
|
def validate_email(self, attrs, source):
|
||||||
attrs[source]
|
attrs[source]
|
||||||
|
@ -573,6 +574,12 @@ class CustomValidationTests(TestCase):
|
||||||
raise serializers.ValidationError("Test not in value")
|
raise serializers.ValidationError("Test not in value")
|
||||||
return attrs
|
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):
|
def test_field_validation(self):
|
||||||
data = {
|
data = {
|
||||||
'email': 'tom@example.com',
|
'email': 'tom@example.com',
|
||||||
|
@ -601,6 +608,35 @@ class CustomValidationTests(TestCase):
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEqual(serializer.errors, {'content': ['This field is required.']})
|
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):
|
def test_wrong_data(self):
|
||||||
"""
|
"""
|
||||||
Make sure that validate_content isn't called if the field input is wrong
|
Make sure that validate_content isn't called if the field input is wrong
|
||||||
|
|
Loading…
Reference in New Issue
Block a user