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).')
|
message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).')
|
||||||
code = 'max_length'
|
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:
|
except ValidationError, e:
|
||||||
errors[f.name] = e.messages
|
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
|
# Form.clean() is run even if other validation fails, so do the
|
||||||
# same with Model.validate() for consistency.
|
# same with Model.validate() for consistency.
|
||||||
try:
|
try:
|
||||||
|
@ -176,19 +176,16 @@ class Field(object):
|
|||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
for v in self.validators:
|
for v in self.validators:
|
||||||
# Don't run complex validators since they need the model instance
|
try:
|
||||||
# and must therefore be run on the model level.
|
v(value)
|
||||||
if not isinstance(v, validators.ComplexValidator):
|
except exceptions.ValidationError, e:
|
||||||
try:
|
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||||
v(value)
|
message = self.error_messages[e.code]
|
||||||
except exceptions.ValidationError, e:
|
if e.params:
|
||||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
message = message % e.params
|
||||||
message = self.error_messages[e.code]
|
errors.append(message)
|
||||||
if e.params:
|
else:
|
||||||
message = message % e.params
|
errors.extend(e.messages)
|
||||||
errors.append(message)
|
|
||||||
else:
|
|
||||||
errors.extend(e.messages)
|
|
||||||
if errors:
|
if errors:
|
||||||
raise exceptions.ValidationError(errors)
|
raise exceptions.ValidationError(errors)
|
||||||
|
|
||||||
|
@ -130,19 +130,16 @@ class Field(object):
|
|||||||
return
|
return
|
||||||
errors = []
|
errors = []
|
||||||
for v in self.validators:
|
for v in self.validators:
|
||||||
# don't run complex validators since they need all_values
|
try:
|
||||||
# and must therefore be run on the form level
|
v(value)
|
||||||
if not isinstance(v, validators.ComplexValidator):
|
except ValidationError, e:
|
||||||
try:
|
if hasattr(e, 'code') and e.code in self.error_messages:
|
||||||
v(value)
|
message = self.error_messages[e.code]
|
||||||
except ValidationError, e:
|
if e.params:
|
||||||
if hasattr(e, 'code') and e.code in self.error_messages:
|
message = message % e.params
|
||||||
message = self.error_messages[e.code]
|
errors.append(message)
|
||||||
if e.params:
|
else:
|
||||||
message = message % e.params
|
errors.extend(e.messages)
|
||||||
errors.append(message)
|
|
||||||
else:
|
|
||||||
errors.extend(e.messages)
|
|
||||||
if errors:
|
if errors:
|
||||||
raise ValidationError(errors)
|
raise ValidationError(errors)
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ Form classes
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import ComplexValidator
|
|
||||||
from django.utils.copycompat import deepcopy
|
from django.utils.copycompat import deepcopy
|
||||||
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
|
||||||
@ -283,31 +282,6 @@ class BaseForm(StrAndUnicode):
|
|||||||
self._errors[name] = self.error_class(e.messages)
|
self._errors[name] = self.error_class(e.messages)
|
||||||
if name in self.cleaned_data:
|
if name in self.cleaned_data:
|
||||||
del self.cleaned_data[name]
|
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:
|
try:
|
||||||
self.cleaned_data = self.clean()
|
self.cleaned_data = self.clean()
|
||||||
except ValidationError, e:
|
except ValidationError, e:
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import ComplexValidator
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
@ -9,14 +8,6 @@ def validate_answer_to_universe(value):
|
|||||||
if value != 42:
|
if value != 42:
|
||||||
raise ValidationError('This is not the answer to life, universe and everything!', code='not42')
|
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):
|
class ModelToValidate(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
created = models.DateTimeField(default=datetime.now)
|
created = models.DateTimeField(default=datetime.now)
|
||||||
@ -24,7 +15,7 @@ class ModelToValidate(models.Model):
|
|||||||
parent = models.ForeignKey('self', blank=True, null=True)
|
parent = models.ForeignKey('self', blank=True, null=True)
|
||||||
email = models.EmailField(blank=True)
|
email = models.EmailField(blank=True)
|
||||||
url = models.URLField(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):
|
def validate(self):
|
||||||
super(ModelToValidate, self).validate()
|
super(ModelToValidate, self).validate()
|
||||||
@ -58,7 +49,7 @@ class CustomMessagesModel(models.Model):
|
|||||||
other = models.IntegerField(blank=True, null=True)
|
other = models.IntegerField(blank=True, null=True)
|
||||||
number = models.IntegerField(
|
number = models.IntegerField(
|
||||||
error_messages={'null': 'NULL', 'not42': 'AAARGH', 'not_equal': '%s != me'},
|
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 modeltests.validation import ValidationTestCase
|
||||||
|
|
||||||
from models import CustomMessagesModel
|
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):
|
def test_custom_simple_validator_message(self):
|
||||||
cmm = CustomMessagesModel(number=12)
|
cmm = CustomMessagesModel(number=12)
|
||||||
self.assertFieldFailsValidationWithMessage(cmm.full_validate, 'number', ['AAARGH'])
|
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!']
|
[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_integer, validate_email, validate_slug, validate_ipv4_address,
|
||||||
validate_comma_separated_integer_list, MaxValueValidator,
|
validate_comma_separated_integer_list, MaxValueValidator,
|
||||||
MinValueValidator, MaxLengthValidator, MinLengthValidator,
|
MinValueValidator, MaxLengthValidator, MinLengthValidator,
|
||||||
RequiredIfOtherFieldBlank, URLValidator, BaseValidator,
|
URLValidator, BaseValidator, RegexValidator,
|
||||||
RegexValidator,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
now = datetime.now()
|
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))
|
setattr(TestSimpleValidators, *get_simple_test_func(validator, expected, value, test_counter))
|
||||||
test_counter += 1
|
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 media import media_tests
|
||||||
|
|
||||||
from fields import FieldsTests
|
from fields import FieldsTests
|
||||||
from validators import TestFormWithValidators, TestFieldWithValidators
|
from validators import TestFieldWithValidators
|
||||||
|
|
||||||
__test__ = {
|
__test__ = {
|
||||||
'extra_tests': extra_tests,
|
'extra_tests': extra_tests,
|
||||||
|
@ -4,9 +4,6 @@ from django import forms
|
|||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
class AlwaysFailingValidator(validators.ComplexValidator):
|
|
||||||
def __call__(self, value, all_values={}, obj=None):
|
|
||||||
raise ValidationError('AlwaysFailingValidator')
|
|
||||||
|
|
||||||
class TestFieldWithValidators(TestCase):
|
class TestFieldWithValidators(TestCase):
|
||||||
def test_all_errors_get_reported(self):
|
def test_all_errors_get_reported(self):
|
||||||
@ -19,16 +16,3 @@ class TestFieldWithValidators(TestCase):
|
|||||||
except ValidationError, e:
|
except ValidationError, e:
|
||||||
self.assertEqual(2, len(e.messages))
|
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