1
0
mirror of https://github.com/django/django.git synced 2025-07-07 11:19:12 +00:00

[soc2009/model-validation] Introduced ComplexValidator and changed the validator handling logic.

Field.validate() now calls all validators except for ComplexValidator
instances which are then run in the form's clean() method.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@10946 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Honza Král 2009-06-08 00:55:07 +00:00
parent ca9cecb702
commit 6d840d9b05
3 changed files with 33 additions and 2 deletions

View File

@ -7,7 +7,7 @@ from django.utils.encoding import smart_unicode
# These values, if given to to_python(), will trigger the self.required check. # These values, if given to to_python(), will trigger the self.required check.
EMPTY_VALUES = (None, '') EMPTY_VALUES = (None, '')
def validate_integer(value, all_values={}, model_instance=None): def validate_integer(value):
try: try:
int(value) int(value)
except (ValueError, TypeError), e: except (ValueError, TypeError), e:
@ -18,6 +18,28 @@ email_re = re.compile(
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
r')@(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain r')@(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
def validate_email(value, all_values={}, model_instance=None): def validate_email(value):
if not email_re.search(smart_unicode(value)): if not email_re.search(smart_unicode(value)):
raise ValidationError(_(u'Enter a valid e-mail address.')) raise ValidationError(_(u'Enter a valid e-mail address.'))
class ComplexValidator(object):
def get_value(self, name, all_values, obj):
assert all_values or obj, "Either all_values or obj must be supplied"
if all_values:
return all_values.get(name, None)
if obj:
return getattr(obj, name, None)
def __call__(self, value, all_values={}, obj=None):
raise NotImplementedError()
class RequiredIfOtherFieldBlank(ComplexValidator):
def __init__(self, other_field):
self.other_field = other_field
def __call__(self, value, all_values={}, obj=None):
if self.get_value(self.other_field, all_values, obj) in EMPTY_VALUES:
if value in EMPTY_VALUES:
raise ValidationError('This field is required if %n is blank.' % self.other_field)

View File

@ -119,6 +119,11 @@ class Field(object):
def validate(self, value): def validate(self, value):
if value in EMPTY_VALUES and self.required: if value in EMPTY_VALUES and self.required:
raise ValidationError(self.error_messages['required']) raise ValidationError(self.error_messages['required'])
for v in self.validators:
# don't run complex validators since they need all_values
# and must therefore be run on the form level
if not isinstance(v, validators.ComplexValidator):
v(value)
def clean(self, value): def clean(self, value):

View File

@ -5,6 +5,7 @@ Form classes
from copy import deepcopy from copy import deepcopy
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import ComplexValidator
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.html import conditional_escape from django.utils.html import conditional_escape
from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
@ -254,6 +255,9 @@ class BaseForm(StrAndUnicode):
if not name in self.cleaned_data: if not name in self.cleaned_data:
continue continue
for v in field.validators: for v in field.validators:
# skip noncomplex validators, they have already been run on the Field
if not isinstance(v, ComplexValidator):
continue
try: try:
v(self.cleaned_data[name], all_values=self.cleaned_data) v(self.cleaned_data[name], all_values=self.cleaned_data)
except ValidationError, e: except ValidationError, e: