Loading django/db/models/fields/__init__.py +6 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import collections import copy import datetime import decimal import itertools import uuid import warnings from base64 import b64decode, b64encode Loading Loading @@ -531,9 +532,11 @@ class Field(RegisterLookupMixin): @cached_property def validators(self): # Some validators can't be created at field initialization time. # This method provides a way to delay their creation until required. return self.default_validators + self._validators """ Some validators can't be created at field initialization time. This method provides a way to delay their creation until required. """ return list(itertools.chain(self.default_validators, self._validators)) def run_validators(self, value): if value in self.empty_values: Loading django/forms/fields.py +3 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ from __future__ import unicode_literals import copy import datetime import itertools import os import re import sys Loading Loading @@ -119,7 +120,8 @@ class Field(object): messages.update(error_messages or {}) self.error_messages = messages self.validators = self.default_validators + validators self.validators = list(itertools.chain(self.default_validators, validators)) super(Field, self).__init__() def prepare_value(self, value): Loading tests/forms_tests/tests/test_validators.py +14 −0 Original line number Diff line number Diff line Loading @@ -52,3 +52,17 @@ class TestFieldWithValidators(TestCase): self.assertFalse(form.is_valid()) self.assertEqual(form.errors['string'], ["Letters only."]) self.assertEqual(form.errors['string'], ["Letters only."]) def test_field_validators_can_be_any_iterable(self): class UserForm(forms.Form): full_name = forms.CharField( max_length=50, validators=( validators.validate_integer, validators.validate_email, ) ) form = UserForm({'full_name': 'not int nor mail'}) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['full_name'], ['Enter a valid integer.', 'Enter a valid email address.']) tests/validation/models.py +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ class ModelToValidate(models.Model): ) url = models.URLField(blank=True) f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe]) f_with_iterable_of_validators = models.IntegerField(blank=True, null=True, validators=(validate_answer_to_universe,)) slug = models.SlugField(blank=True) def clean(self): Loading tests/validation/test_validators.py +14 −2 Original line number Diff line number Diff line Loading @@ -6,14 +6,26 @@ from .models import ModelToValidate class TestModelsWithValidators(ValidationTestCase): def test_custom_validator_passes_for_correct_value(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42) mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42, f_with_iterable_of_validators=42) self.assertIsNone(mtv.full_clean()) def test_custom_validator_raises_error_for_incorrect_value(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12) mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12, f_with_iterable_of_validators=42) self.assertFailsValidation(mtv.full_clean, ['f_with_custom_validator']) self.assertFieldFailsValidationWithMessage( mtv.full_clean, 'f_with_custom_validator', ['This is not the answer to life, universe and everything!'] ) def test_field_validators_can_be_any_iterable(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42, f_with_iterable_of_validators=12) self.assertFailsValidation(mtv.full_clean, ['f_with_iterable_of_validators']) self.assertFieldFailsValidationWithMessage( mtv.full_clean, 'f_with_iterable_of_validators', ['This is not the answer to life, universe and everything!'] ) Loading
django/db/models/fields/__init__.py +6 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import collections import copy import datetime import decimal import itertools import uuid import warnings from base64 import b64decode, b64encode Loading Loading @@ -531,9 +532,11 @@ class Field(RegisterLookupMixin): @cached_property def validators(self): # Some validators can't be created at field initialization time. # This method provides a way to delay their creation until required. return self.default_validators + self._validators """ Some validators can't be created at field initialization time. This method provides a way to delay their creation until required. """ return list(itertools.chain(self.default_validators, self._validators)) def run_validators(self, value): if value in self.empty_values: Loading
django/forms/fields.py +3 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ from __future__ import unicode_literals import copy import datetime import itertools import os import re import sys Loading Loading @@ -119,7 +120,8 @@ class Field(object): messages.update(error_messages or {}) self.error_messages = messages self.validators = self.default_validators + validators self.validators = list(itertools.chain(self.default_validators, validators)) super(Field, self).__init__() def prepare_value(self, value): Loading
tests/forms_tests/tests/test_validators.py +14 −0 Original line number Diff line number Diff line Loading @@ -52,3 +52,17 @@ class TestFieldWithValidators(TestCase): self.assertFalse(form.is_valid()) self.assertEqual(form.errors['string'], ["Letters only."]) self.assertEqual(form.errors['string'], ["Letters only."]) def test_field_validators_can_be_any_iterable(self): class UserForm(forms.Form): full_name = forms.CharField( max_length=50, validators=( validators.validate_integer, validators.validate_email, ) ) form = UserForm({'full_name': 'not int nor mail'}) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['full_name'], ['Enter a valid integer.', 'Enter a valid email address.'])
tests/validation/models.py +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ class ModelToValidate(models.Model): ) url = models.URLField(blank=True) f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe]) f_with_iterable_of_validators = models.IntegerField(blank=True, null=True, validators=(validate_answer_to_universe,)) slug = models.SlugField(blank=True) def clean(self): Loading
tests/validation/test_validators.py +14 −2 Original line number Diff line number Diff line Loading @@ -6,14 +6,26 @@ from .models import ModelToValidate class TestModelsWithValidators(ValidationTestCase): def test_custom_validator_passes_for_correct_value(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42) mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42, f_with_iterable_of_validators=42) self.assertIsNone(mtv.full_clean()) def test_custom_validator_raises_error_for_incorrect_value(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12) mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12, f_with_iterable_of_validators=42) self.assertFailsValidation(mtv.full_clean, ['f_with_custom_validator']) self.assertFieldFailsValidationWithMessage( mtv.full_clean, 'f_with_custom_validator', ['This is not the answer to life, universe and everything!'] ) def test_field_validators_can_be_any_iterable(self): mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42, f_with_iterable_of_validators=12) self.assertFailsValidation(mtv.full_clean, ['f_with_iterable_of_validators']) self.assertFieldFailsValidationWithMessage( mtv.full_clean, 'f_with_iterable_of_validators', ['This is not the answer to life, universe and everything!'] )