mirror of
https://github.com/django/django.git
synced 2025-07-06 18:59:13 +00:00
[soc2009/model-validation] Removed the ComplexValidator code in preparation for merging this branch into trunk. It will likely come back in some other form sometime after the merge.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@12078 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
556132f75b
commit
a54ed5ad1e
@ -135,26 +135,3 @@ class MaxLengthValidator(BaseValidator):
|
||||
message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).')
|
||||
code = 'max_length'
|
||||
|
||||
|
||||
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 %s is blank.' % self.other_field)
|
||||
|
||||
|
@ -799,26 +799,6 @@ class Model(object):
|
||||
except ValidationError, e:
|
||||
errors[f.name] = e.messages
|
||||
|
||||
# run complex validators after the fields have been cleaned since they
|
||||
# need access to model_instance.
|
||||
for f in self._meta.fields:
|
||||
if f.name in errors:
|
||||
continue
|
||||
|
||||
value = getattr(self, f.attname)
|
||||
for v in f.validators:
|
||||
if isinstance(v, validators.ComplexValidator):
|
||||
try:
|
||||
v(value, obj=self)
|
||||
except ValidationError, e:
|
||||
error_list = errors.setdefault(f.name, [])
|
||||
if hasattr(e, 'code') and e.code in f.error_messages:
|
||||
message = f.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
error_list.append(message)
|
||||
else:
|
||||
error_list.extend(e.messages)
|
||||
# Form.clean() is run even if other validation fails, so do the
|
||||
# same with Model.validate() for consistency.
|
||||
try:
|
||||
|
@ -176,19 +176,16 @@ class Field(object):
|
||||
|
||||
errors = []
|
||||
for v in self.validators:
|
||||
# Don't run complex validators since they need the model instance
|
||||
# and must therefore be run on the model level.
|
||||
if not isinstance(v, validators.ComplexValidator):
|
||||
try:
|
||||
v(value)
|
||||
except exceptions.ValidationError, e:
|
||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||
message = self.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
errors.append(message)
|
||||
else:
|
||||
errors.extend(e.messages)
|
||||
try:
|
||||
v(value)
|
||||
except exceptions.ValidationError, e:
|
||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||
message = self.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
errors.append(message)
|
||||
else:
|
||||
errors.extend(e.messages)
|
||||
if errors:
|
||||
raise exceptions.ValidationError(errors)
|
||||
|
||||
|
@ -130,19 +130,16 @@ class Field(object):
|
||||
return
|
||||
errors = []
|
||||
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):
|
||||
try:
|
||||
v(value)
|
||||
except ValidationError, e:
|
||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||
message = self.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
errors.append(message)
|
||||
else:
|
||||
errors.extend(e.messages)
|
||||
try:
|
||||
v(value)
|
||||
except ValidationError, e:
|
||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||
message = self.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
errors.append(message)
|
||||
else:
|
||||
errors.extend(e.messages)
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
|
@ -3,7 +3,6 @@ Form classes
|
||||
"""
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import ComplexValidator
|
||||
from django.utils.copycompat import deepcopy
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.html import conditional_escape
|
||||
@ -283,31 +282,6 @@ class BaseForm(StrAndUnicode):
|
||||
self._errors[name] = self.error_class(e.messages)
|
||||
if name in self.cleaned_data:
|
||||
del self.cleaned_data[name]
|
||||
|
||||
# Run complex validators after the fields have been cleaned since they
|
||||
# need access to all_values.
|
||||
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):
|
||||
continue
|
||||
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') and e.code in field.error_messages:
|
||||
message = field.error_messages[e.code]
|
||||
if e.params:
|
||||
message = message % e.params
|
||||
error_list.append(message)
|
||||
else:
|
||||
error_list.extend(e.messages)
|
||||
if failed:
|
||||
del self.cleaned_data[name]
|
||||
try:
|
||||
self.cleaned_data = self.clean()
|
||||
except ValidationError, e:
|
||||
|
@ -1,7 +1,6 @@
|
||||
from datetime import datetime
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import ComplexValidator
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
|
||||
@ -9,14 +8,6 @@ def validate_answer_to_universe(value):
|
||||
if value != 42:
|
||||
raise ValidationError('This is not the answer to life, universe and everything!', code='not42')
|
||||
|
||||
class ValidateFieldNotEqualsOtherField(ComplexValidator):
|
||||
def __init__(self, other_field):
|
||||
self.other_field = other_field
|
||||
|
||||
def __call__(self, value, all_values={}, obj=None):
|
||||
if value == self.get_value(self.other_field, all_values, obj):
|
||||
raise ValidationError("Must not equal to %r's value" % self.other_field, code='not_equal', params=(self.other_field,))
|
||||
|
||||
class ModelToValidate(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
created = models.DateTimeField(default=datetime.now)
|
||||
@ -24,7 +15,7 @@ class ModelToValidate(models.Model):
|
||||
parent = models.ForeignKey('self', blank=True, null=True)
|
||||
email = models.EmailField(blank=True)
|
||||
url = models.URLField(blank=True)
|
||||
f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe, ValidateFieldNotEqualsOtherField('number')])
|
||||
f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe])
|
||||
|
||||
def validate(self):
|
||||
super(ModelToValidate, self).validate()
|
||||
@ -58,7 +49,7 @@ class CustomMessagesModel(models.Model):
|
||||
other = models.IntegerField(blank=True, null=True)
|
||||
number = models.IntegerField(
|
||||
error_messages={'null': 'NULL', 'not42': 'AAARGH', 'not_equal': '%s != me'},
|
||||
validators=[validate_answer_to_universe, ValidateFieldNotEqualsOtherField('other')]
|
||||
validators=[validate_answer_to_universe]
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,11 +1,8 @@
|
||||
from modeltests.validation import ValidationTestCase
|
||||
|
||||
from models import CustomMessagesModel
|
||||
class CustomMessagesTest(ValidationTestCase):
|
||||
def test_custom_complex_validator_message(self):
|
||||
cmm = CustomMessagesModel(number=42, other=42)
|
||||
self.assertFieldFailsValidationWithMessage(cmm.full_validate, 'number', ['other != me'])
|
||||
|
||||
|
||||
class CustomMessagesTest(ValidationTestCase):
|
||||
def test_custom_simple_validator_message(self):
|
||||
cmm = CustomMessagesModel(number=12)
|
||||
self.assertFieldFailsValidationWithMessage(cmm.full_validate, 'number', ['AAARGH'])
|
||||
|
@ -18,19 +18,3 @@ class TestModelsWithValidators(ValidationTestCase):
|
||||
[u'This is not the answer to life, universe and everything!']
|
||||
)
|
||||
|
||||
def test_custom_complex_validator_raises_error_for_incorrect_value(self):
|
||||
mtv = ModelToValidate(number=42, name='Some Name', f_with_custom_validator=42)
|
||||
self.assertFailsValidation(mtv.full_validate, ['f_with_custom_validator'])
|
||||
self.assertFieldFailsValidationWithMessage(
|
||||
mtv.full_validate,
|
||||
'f_with_custom_validator',
|
||||
[u"Must not equal to 'number''s value"]
|
||||
)
|
||||
|
||||
def test_complex_validator_isnt_run_if_field_doesnt_validate(self):
|
||||
mtv = ModelToValidate(number=32, name='Some Name', f_with_custom_validator=32)
|
||||
self.assertFieldFailsValidationWithMessage(
|
||||
mtv.full_validate,
|
||||
'f_with_custom_validator',
|
||||
[u'This is not the answer to life, universe and everything!']
|
||||
)
|
||||
|
@ -9,8 +9,7 @@ from django.core.validators import (
|
||||
validate_integer, validate_email, validate_slug, validate_ipv4_address,
|
||||
validate_comma_separated_integer_list, MaxValueValidator,
|
||||
MinValueValidator, MaxLengthValidator, MinLengthValidator,
|
||||
RequiredIfOtherFieldBlank, URLValidator, BaseValidator,
|
||||
RegexValidator,
|
||||
URLValidator, BaseValidator, RegexValidator,
|
||||
)
|
||||
|
||||
now = datetime.now()
|
||||
@ -153,32 +152,3 @@ for validator, value, expected in SIMPLE_VALIDATORS_VALUES:
|
||||
setattr(TestSimpleValidators, *get_simple_test_func(validator, expected, value, test_counter))
|
||||
test_counter += 1
|
||||
|
||||
class TestComplexValidators(TestCase):
|
||||
pass
|
||||
|
||||
COMPLEX_VALIDATORS_VALUES = (
|
||||
#(validator, value, all_values, obj, expected),
|
||||
(RequiredIfOtherFieldBlank('other'), 'given', {'other': 'given'}, None, None),
|
||||
(RequiredIfOtherFieldBlank('other'), '', {'other': 'given'}, None, None),
|
||||
(RequiredIfOtherFieldBlank('other'), 'given', {}, None, AssertionError),
|
||||
(RequiredIfOtherFieldBlank('other'), '', {}, None, AssertionError),
|
||||
(RequiredIfOtherFieldBlank('other'), '', {'other': ''}, None, ValidationError),
|
||||
)
|
||||
|
||||
def get_complex_test_func(validator, expected, value, all_values, obj, num):
|
||||
if isinstance(expected, type) and issubclass(expected, Exception):
|
||||
test_mask = 'test_%s_raises_error_%d'
|
||||
def test_func(self):
|
||||
self.assertRaises(expected, validator, value, all_values=all_values, obj=obj)
|
||||
else:
|
||||
test_mask = 'test_%s_%d'
|
||||
def test_func(self):
|
||||
self.assertEqual(expected, validator(value, all_values=all_values, obj=obj))
|
||||
test_name = test_mask % (validator.__class__.__name__, num)
|
||||
return test_name, test_func
|
||||
|
||||
test_counter = {}
|
||||
for validator, value, all_values, obj, expected in COMPLEX_VALIDATORS_VALUES:
|
||||
num = test_counter[validator.__class__.__name__] = test_counter.setdefault(validator.__class__.__name__, 0) + 1
|
||||
setattr(TestComplexValidators, *get_complex_test_func(validator, expected, value, all_values, obj, num))
|
||||
|
||||
|
@ -38,7 +38,7 @@ from formsets import tests as formset_tests
|
||||
from media import media_tests
|
||||
|
||||
from fields import FieldsTests
|
||||
from validators import TestFormWithValidators, TestFieldWithValidators
|
||||
from validators import TestFieldWithValidators
|
||||
|
||||
__test__ = {
|
||||
'extra_tests': extra_tests,
|
||||
|
@ -4,9 +4,6 @@ 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):
|
||||
@ -19,16 +16,3 @@ class TestFieldWithValidators(TestCase):
|
||||
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'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user