Skip to content

Commit 1ece516

Browse files
Si Fengcarltongibson
authored andcommitted
Adjusted field validators to accept iterables. (#6282)
Closes 6280.
1 parent 6de33ef commit 1ece516

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

rest_framework/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ def __init__(self, read_only=False, write_only=False,
350350
self.default_empty_html = default
351351

352352
if validators is not None:
353-
self.validators = validators[:]
353+
self.validators = list(validators)
354354

355355
# These are set up by `.bind()` when the field is added to a serializer.
356356
self.field_name = None
@@ -410,7 +410,7 @@ def validators(self, validators):
410410
self._validators = validators
411411

412412
def get_validators(self):
413-
return self.default_validators[:]
413+
return list(self.default_validators)
414414

415415
def get_initial(self):
416416
"""

rest_framework/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ def get_validators(self):
393393
# Used by the lazily-evaluated `validators` property.
394394
meta = getattr(self, 'Meta', None)
395395
validators = getattr(meta, 'validators', None)
396-
return validators[:] if validators else []
396+
return list(validators) if validators else []
397397

398398
def get_initial(self):
399399
if hasattr(self, 'initial_data'):
@@ -1480,7 +1480,7 @@ def get_validators(self):
14801480
# If the validators have been declared explicitly then use that.
14811481
validators = getattr(getattr(self, 'Meta', None), 'validators', None)
14821482
if validators is not None:
1483-
return validators[:]
1483+
return list(validators)
14841484

14851485
# Otherwise use the default set of validators.
14861486
return (

tests/test_fields.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,25 @@ def test_null_bytes(self):
740740
'Null characters are not allowed.'
741741
]
742742

743+
def test_iterable_validators(self):
744+
"""
745+
Ensure `validators` parameter is compatible with reasonable iterables.
746+
"""
747+
value = 'example'
748+
749+
for validators in ([], (), set()):
750+
field = serializers.CharField(validators=validators)
751+
field.run_validation(value)
752+
753+
def raise_exception(value):
754+
raise exceptions.ValidationError('Raised error')
755+
756+
for validators in ([raise_exception], (raise_exception,), set([raise_exception])):
757+
field = serializers.CharField(validators=validators)
758+
with pytest.raises(serializers.ValidationError) as exc_info:
759+
field.run_validation(value)
760+
assert exc_info.value.detail == ['Raised error']
761+
743762

744763
class TestEmailField(FieldValues):
745764
"""

tests/test_serializer.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import pytest
1111
from django.db import models
1212

13-
from rest_framework import fields, relations, serializers
13+
from rest_framework import exceptions, fields, relations, serializers
1414
from rest_framework.compat import unicode_repr
1515
from rest_framework.fields import Field
1616

@@ -183,6 +183,38 @@ def to_internal_value(self, data):
183183
assert serializer.validated_data.coords[1] == 50.941357
184184
assert serializer.errors == {}
185185

186+
def test_iterable_validators(self):
187+
"""
188+
Ensure `validators` parameter is compatible with reasonable iterables.
189+
"""
190+
data = {'char': 'abc', 'integer': 123}
191+
192+
for validators in ([], (), set()):
193+
class ExampleSerializer(serializers.Serializer):
194+
char = serializers.CharField(validators=validators)
195+
integer = serializers.IntegerField()
196+
197+
serializer = ExampleSerializer(data=data)
198+
assert serializer.is_valid()
199+
assert serializer.validated_data == data
200+
assert serializer.errors == {}
201+
202+
def raise_exception(value):
203+
raise exceptions.ValidationError('Raised error')
204+
205+
for validators in ([raise_exception], (raise_exception,), set([raise_exception])):
206+
class ExampleSerializer(serializers.Serializer):
207+
char = serializers.CharField(validators=validators)
208+
integer = serializers.IntegerField()
209+
210+
serializer = ExampleSerializer(data=data)
211+
assert not serializer.is_valid()
212+
assert serializer.data == data
213+
assert serializer.validated_data == {}
214+
assert serializer.errors == {'char': [
215+
exceptions.ErrorDetail(string='Raised error', code='invalid')
216+
]}
217+
186218

187219
class TestValidateMethod:
188220
def test_non_field_error_validate_method(self):

0 commit comments

Comments
 (0)