summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoïc Bistuer <loic.bistuer@gmail.com>2016-04-22 07:18:43 +0700
committerLoïc Bistuer <loic.bistuer@gmail.com>2016-04-22 09:38:47 +0700
commita885bca1dfe5905788ebb9f3a6557822ce3d9e9d (patch)
treefcbd9544afa472e4e7dbcb3b9b05d84c2d22456c
parentec6121693f112ae33b653b4364e812722d2eb567 (diff)
Fixed #26528 -- Allowed any iterable (e.g. tuple) as validators kwarg for form/model fields.
-rw-r--r--django/db/models/fields/__init__.py9
-rw-r--r--django/forms/fields.py4
-rw-r--r--tests/forms_tests/tests/test_validators.py14
-rw-r--r--tests/validation/models.py2
-rw-r--r--tests/validation/test_validators.py16
5 files changed, 39 insertions, 6 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index a4018dd6e9..1e04858344 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -5,6 +5,7 @@ import collections
import copy
import datetime
import decimal
+import itertools
import uuid
import warnings
from base64 import b64decode, b64encode
@@ -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:
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 9af85c86e3..f3f8756e39 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import copy
import datetime
+import itertools
import os
import re
import sys
@@ -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):
diff --git a/tests/forms_tests/tests/test_validators.py b/tests/forms_tests/tests/test_validators.py
index 8c348d600d..e0afd62101 100644
--- a/tests/forms_tests/tests/test_validators.py
+++ b/tests/forms_tests/tests/test_validators.py
@@ -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.'])
diff --git a/tests/validation/models.py b/tests/validation/models.py
index 83b998c38f..2e2a144cb6 100644
--- a/tests/validation/models.py
+++ b/tests/validation/models.py
@@ -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):
diff --git a/tests/validation/test_validators.py b/tests/validation/test_validators.py
index d06605eeca..4a3c99f08b 100644
--- a/tests/validation/test_validators.py
+++ b/tests/validation/test_validators.py
@@ -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!']
+ )