summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHonza Král <honza.kral@gmail.com>2009-06-08 00:55:07 +0000
committerHonza Král <honza.kral@gmail.com>2009-06-08 00:55:07 +0000
commit6d840d9b05f62a4eded37c6cc2da624a41d92e07 (patch)
tree15c41227204e54b72db9816e56e89a66a690cca1
parentca9cecb70280d55bff0e4422e996f40f8e1ea8ca (diff)
[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
-rw-r--r--django/core/validators.py26
-rw-r--r--django/forms/fields.py5
-rw-r--r--django/forms/forms.py4
3 files changed, 33 insertions, 2 deletions
diff --git a/django/core/validators.py b/django/core/validators.py
index 8ac9a96cc7..46b1e4fc36 100644
--- a/django/core/validators.py
+++ b/django/core/validators.py
@@ -7,7 +7,7 @@ from django.utils.encoding import smart_unicode
# These values, if given to to_python(), will trigger the self.required check.
EMPTY_VALUES = (None, '')
-def validate_integer(value, all_values={}, model_instance=None):
+def validate_integer(value):
try:
int(value)
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')@(?:[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)):
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)
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 9446ed2eea..d65edd7047 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -119,6 +119,11 @@ class Field(object):
def validate(self, value):
if value in EMPTY_VALUES and self.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):
diff --git a/django/forms/forms.py b/django/forms/forms.py
index b5c0fc06e0..912fd7c031 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -5,6 +5,7 @@ Form classes
from copy import deepcopy
from django.core.exceptions import ValidationError
+from django.core.validators import ComplexValidator
from django.utils.datastructures import SortedDict
from django.utils.html import conditional_escape
from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
@@ -254,6 +255,9 @@ class BaseForm(StrAndUnicode):
if not name in self.cleaned_data:
continue
for v in field.validators:
+ # skip noncomplex validators, they have already been run on the Field
+ if not isinstance(v, ComplexValidator):
+ continue
try:
v(self.cleaned_data[name], all_values=self.cleaned_data)
except ValidationError, e: