diff --git a/django/core/validators.py b/django/core/validators.py
index 6cd290f..4515ca7 100644
|
a
|
b
|
class MaxLengthValidator(BaseValidator):
|
| 135 | 135 | message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).') |
| 136 | 136 | code = 'max_length' |
| 137 | 137 | |
| | 138 | |
| | 139 | |
| | 140 | |
| | 141 | |
| | 142 | |
| | 143 | |
| | 144 | |
| | 145 | |
| | 146 | |
| | 147 | |
| | 148 | |
| | 149 | |
| | 150 | |
| | 151 | |
| | 152 | |
| | 153 | |
| | 154 | |
| | 155 | |
| | 156 | |
| | 157 | |
| | 158 | |
| | 159 | |
| | 160 | |
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 660c570..eace314 100644
|
a
|
b
|
class Model(object):
|
| 799 | 799 | except ValidationError, e: |
| 800 | 800 | errors[f.name] = e.messages |
| 801 | 801 | |
| | 802 | |
| | 803 | |
| | 804 | |
| | 805 | |
| | 806 | |
| | 807 | |
| | 808 | |
| | 809 | |
| | 810 | |
| | 811 | |
| | 812 | |
| | 813 | |
| | 814 | |
| | 815 | |
| | 816 | |
| | 817 | |
| | 818 | |
| | 819 | |
| | 820 | |
| | 821 | |
| 802 | 822 | # Form.clean() is run even if other validation fails, so do the |
| 803 | 823 | # same with Model.validate() for consistency. |
| 804 | 824 | try: |
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 5c36437..96fc36f 100644
|
a
|
b
|
class Field(object):
|
| 176 | 176 | |
| 177 | 177 | errors = [] |
| 178 | 178 | for v in self.validators: |
| 179 | | try: |
| 180 | | v(value) |
| 181 | | except exceptions.ValidationError, e: |
| 182 | | if hasattr(e, 'code') and e.code in self.error_messages: |
| 183 | | message = self.error_messages[e.code] |
| 184 | | if e.params: |
| 185 | | message = message % e.params |
| 186 | | errors.append(message) |
| 187 | | else: |
| 188 | | errors.extend(e.messages) |
| | 179 | # Don't run complex validators since they need the model instance |
| | 180 | # and must therefore be run on the model level. |
| | 181 | if not isinstance(v, validators.ComplexValidator): |
| | 182 | try: |
| | 183 | v(value) |
| | 184 | except exceptions.ValidationError, e: |
| | 185 | if hasattr(e, 'code') and e.code in self.error_messages: |
| | 186 | message = self.error_messages[e.code] |
| | 187 | if e.params: |
| | 188 | message = message % e.params |
| | 189 | errors.append(message) |
| | 190 | else: |
| | 191 | errors.extend(e.messages) |
| 189 | 192 | if errors: |
| 190 | 193 | raise exceptions.ValidationError(errors) |
| 191 | 194 | |
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 23a88d6..40e3d90 100644
|
a
|
b
|
class Field(object):
|
| 130 | 130 | return |
| 131 | 131 | errors = [] |
| 132 | 132 | for v in self.validators: |
| 133 | | try: |
| 134 | | v(value) |
| 135 | | except ValidationError, e: |
| 136 | | if hasattr(e, 'code') and e.code in self.error_messages: |
| 137 | | message = self.error_messages[e.code] |
| 138 | | if e.params: |
| 139 | | message = message % e.params |
| 140 | | errors.append(message) |
| 141 | | else: |
| 142 | | errors.extend(e.messages) |
| | 133 | # don't run complex validators since they need all_values |
| | 134 | # and must therefore be run on the form level |
| | 135 | if not isinstance(v, validators.ComplexValidator): |
| | 136 | try: |
| | 137 | v(value) |
| | 138 | except ValidationError, e: |
| | 139 | if hasattr(e, 'code') and e.code in self.error_messages: |
| | 140 | message = self.error_messages[e.code] |
| | 141 | if e.params: |
| | 142 | message = message % e.params |
| | 143 | errors.append(message) |
| | 144 | else: |
| | 145 | errors.extend(e.messages) |
| 143 | 146 | if errors: |
| 144 | 147 | raise ValidationError(errors) |
| 145 | 148 | |
diff --git a/django/forms/forms.py b/django/forms/forms.py
index d484300..5b8a4d0 100644
|
a
|
b
|
Form classes
|
| 3 | 3 | """ |
| 4 | 4 | |
| 5 | 5 | from django.core.exceptions import ValidationError |
| | 6 | |
| 6 | 7 | from django.utils.copycompat import deepcopy |
| 7 | 8 | from django.utils.datastructures import SortedDict |
| 8 | 9 | from django.utils.html import conditional_escape |
| … |
… |
class BaseForm(StrAndUnicode):
|
| 282 | 283 | self._errors[name] = self.error_class(e.messages) |
| 283 | 284 | if name in self.cleaned_data: |
| 284 | 285 | del self.cleaned_data[name] |
| | 286 | |
| | 287 | |
| | 288 | |
| | 289 | |
| | 290 | |
| | 291 | |
| | 292 | |
| | 293 | |
| | 294 | |
| | 295 | |
| | 296 | |
| | 297 | |
| | 298 | |
| | 299 | |
| | 300 | |
| | 301 | |
| | 302 | |
| | 303 | |
| | 304 | |
| | 305 | |
| | 306 | |
| | 307 | |
| | 308 | |
| | 309 | |
| | 310 | |
| 285 | 311 | try: |
| 286 | 312 | self.cleaned_data = self.clean() |
| 287 | 313 | except ValidationError, e: |
diff --git a/tests/modeltests/validation/models.py b/tests/modeltests/validation/models.py
index db5100b..1260417 100644
|
a
|
b
|
|
| 1 | 1 | from datetime import datetime |
| 2 | 2 | |
| 3 | 3 | from django.core.exceptions import ValidationError |
| | 4 | |
| 4 | 5 | from django.db import models |
| 5 | 6 | from django.test import TestCase |
| 6 | 7 | |
| … |
… |
def validate_answer_to_universe(value):
|
| 8 | 9 | if value != 42: |
| 9 | 10 | raise ValidationError('This is not the answer to life, universe and everything!', code='not42') |
| 10 | 11 | |
| | 12 | |
| | 13 | |
| | 14 | |
| | 15 | |
| | 16 | |
| | 17 | |
| | 18 | |
| | 19 | |
| 11 | 20 | class ModelToValidate(models.Model): |
| 12 | 21 | name = models.CharField(max_length=100) |
| 13 | 22 | created = models.DateTimeField(default=datetime.now) |
| … |
… |
class ModelToValidate(models.Model):
|
| 15 | 24 | parent = models.ForeignKey('self', blank=True, null=True) |
| 16 | 25 | email = models.EmailField(blank=True) |
| 17 | 26 | url = models.URLField(blank=True) |
| 18 | | f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe]) |
| | 27 | f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe]) |
| 19 | 28 | |
| 20 | 29 | def validate(self): |
| 21 | 30 | super(ModelToValidate, self).validate() |
| … |
… |
class CustomMessagesModel(models.Model):
|
| 49 | 58 | other = models.IntegerField(blank=True, null=True) |
| 50 | 59 | number = models.IntegerField( |
| 51 | 60 | error_messages={'null': 'NULL', 'not42': 'AAARGH', 'not_equal': '%s != me'}, |
| 52 | | validators=[validate_answer_to_universe] |
| | 61 | validators=[validate_answer_to_universe] |
| 53 | 62 | ) |
| 54 | 63 | |
| 55 | 64 | |
diff --git a/tests/modeltests/validation/test_custom_messages.py b/tests/modeltests/validation/test_custom_messages.py
index 9a958a0..e543dbd 100644
|
a
|
b
|
|
| 1 | 1 | from modeltests.validation import ValidationTestCase |
| 2 | | from models import CustomMessagesModel |
| 3 | | |
| 4 | 2 | |
| | 3 | |
| 5 | 4 | class CustomMessagesTest(ValidationTestCase): |
| | 5 | |
| | 6 | |
| | 7 | |
| | 8 | |
| 6 | 9 | def test_custom_simple_validator_message(self): |
| 7 | 10 | cmm = CustomMessagesModel(number=12) |
| 8 | 11 | self.assertFieldFailsValidationWithMessage(cmm.full_validate, 'number', ['AAARGH']) |
diff --git a/tests/modeltests/validation/validators.py b/tests/modeltests/validation/validators.py
index d46d0c5..d54aab6 100644
|
a
|
b
|
class TestModelsWithValidators(ValidationTestCase):
|
| 18 | 18 | [u'This is not the answer to life, universe and everything!'] |
| 19 | 19 | ) |
| 20 | 20 | |
| | 21 | |
| | 22 | |
| | 23 | |
| | 24 | |
| | 25 | |
| | 26 | |
| | 27 | |
| | 28 | |
| | 29 | |
| | 30 | |
| | 31 | |
| | 32 | |
| | 33 | |
| | 34 | |
| | 35 | |
| | 36 | |
diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py
index 1108ee8..331f6f0 100644
|
a
|
b
|
from django.core.validators import (
|
| 9 | 9 | validate_integer, validate_email, validate_slug, validate_ipv4_address, |
| 10 | 10 | validate_comma_separated_integer_list, MaxValueValidator, |
| 11 | 11 | MinValueValidator, MaxLengthValidator, MinLengthValidator, |
| 12 | | URLValidator, BaseValidator, RegexValidator, |
| | 12 | RequiredIfOtherFieldBlank, URLValidator, BaseValidator, |
| | 13 | RegexValidator, |
| 13 | 14 | ) |
| 14 | 15 | |
| 15 | 16 | now = datetime.now() |
| … |
… |
for validator, value, expected in SIMPLE_VALIDATORS_VALUES:
|
| 152 | 153 | setattr(TestSimpleValidators, *get_simple_test_func(validator, expected, value, test_counter)) |
| 153 | 154 | test_counter += 1 |
| 154 | 155 | |
| | 156 | |
| | 157 | |
| | 158 | |
| | 159 | |
| | 160 | |
| | 161 | |
| | 162 | |
| | 163 | |
| | 164 | |
| | 165 | |
| | 166 | |
| | 167 | |
| | 168 | |
| | 169 | |
| | 170 | |
| | 171 | |
| | 172 | |
| | 173 | |
| | 174 | |
| | 175 | |
| | 176 | |
| | 177 | |
| | 178 | |
| | 179 | |
| | 180 | |
| | 181 | |
| | 182 | |
| | 183 | |
| | 184 | |
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index db70500..e9ae948 100644
|
a
|
b
|
from formsets import tests as formset_tests
|
| 38 | 38 | from media import media_tests |
| 39 | 39 | |
| 40 | 40 | from fields import FieldsTests |
| 41 | | from validators import TestFieldWithValidators |
| | 41 | from validators import TestFieldWithValidators |
| 42 | 42 | |
| 43 | 43 | __test__ = { |
| 44 | 44 | 'extra_tests': extra_tests, |
diff --git a/tests/regressiontests/forms/validators.py b/tests/regressiontests/forms/validators.py
index b75a14e..becf4e2 100644
|
a
|
b
|
from django import forms
|
| 4 | 4 | from django.core import validators |
| 5 | 5 | from django.core.exceptions import ValidationError |
| 6 | 6 | |
| | 7 | |
| | 8 | |
| | 9 | |
| 7 | 10 | |
| 8 | 11 | class TestFieldWithValidators(TestCase): |
| 9 | 12 | def test_all_errors_get_reported(self): |
| … |
… |
class TestFieldWithValidators(TestCase):
|
| 16 | 19 | except ValidationError, e: |
| 17 | 20 | self.assertEqual(2, len(e.messages)) |
| 18 | 21 | |
| | 22 | |
| | 23 | |
| | 24 | |
| | 25 | |
| | 26 | |
| | 27 | |
| | 28 | |
| | 29 | |
| | 30 | |
| | 31 | |
| | 32 | |
| | 33 | |
| | 34 | |