From 63f244f14413e0981c76dda8bf6f76e7b9df3d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Honza=20Kr=C3=A1l?= Date: Sun, 5 Jul 2009 13:26:57 +0000 Subject: [PATCH] [soc2009/model-validation] Make sure that all validators in the same group (simple/complex) get run even if they all fail and we get all their messages. git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@11185 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/forms/forms.py | 7 +++-- tests/regressiontests/forms/tests.py | 1 + tests/regressiontests/forms/validators.py | 34 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/regressiontests/forms/validators.py diff --git a/django/forms/forms.py b/django/forms/forms.py index bb5b086d05..c7f07657d4 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -254,6 +254,7 @@ class BaseForm(StrAndUnicode): for name, field in self.fields.items(): if not name in self.cleaned_data: continue + failed = False for v in field.validators: # skip noncomplex validators, they have already been run on the Field if not isinstance(v, ComplexValidator): @@ -261,14 +262,14 @@ class BaseForm(StrAndUnicode): try: v(self.cleaned_data[name], all_values=self.cleaned_data) except ValidationError, e: + failed = True error_list = self._errors.setdefault(name, self.error_class()) if hasattr(e, 'code'): error_list.append(field.error_messages.get(e.code, e.messages[0])) else: error_list.extend(e.messages) - if name in self.cleaned_data: - del self.cleaned_data[name] - + if failed: + del self.cleaned_data[name] try: self.cleaned_data = self.clean() except ValidationError, e: diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index c6881daff4..ef7326735d 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -32,6 +32,7 @@ from formsets import tests as formset_tests from media import media_tests from fields import TestFields +from validators import TestFormWithValidators, TestFieldWithValidators __test__ = { 'extra_tests': extra_tests, diff --git a/tests/regressiontests/forms/validators.py b/tests/regressiontests/forms/validators.py new file mode 100644 index 0000000000..becf4e2825 --- /dev/null +++ b/tests/regressiontests/forms/validators.py @@ -0,0 +1,34 @@ +from unittest import TestCase + +from django import forms +from django.core import validators +from django.core.exceptions import ValidationError + +class AlwaysFailingValidator(validators.ComplexValidator): + def __call__(self, value, all_values={}, obj=None): + raise ValidationError('AlwaysFailingValidator') + +class TestFieldWithValidators(TestCase): + def test_all_errors_get_reported(self): + field = forms.CharField( + validators=[validators.validate_integer, validators.validate_email,] + ) + self.assertRaises(ValidationError, field.clean, 'not int nor mail') + try: + field.clean('not int nor mail') + except ValidationError, e: + self.assertEqual(2, len(e.messages)) + +class TestFormWithValidators(TestCase): + def test_all_complex_validators_get_run_even_if_they_fail(self): + class MyForm(forms.Form): + validator_field = forms.CharField( + validators=[ + AlwaysFailingValidator(), + AlwaysFailingValidator(), + ] + ) + form = MyForm({'validator_field': 'some value'}) + self.assertFalse(form.is_valid()) + self.assertEqual(['validator_field'], form.errors.keys()) + self.assertEqual(['AlwaysFailingValidator', 'AlwaysFailingValidator'], form.errors['validator_field'])