1
0
mirror of https://github.com/django/django.git synced 2025-07-06 18:59:13 +00:00

[soc2009/model-validation] validators refactoring

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@11457 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Honza Král 2009-08-15 13:34:42 +00:00
parent 05524abf1b
commit 9578491379
3 changed files with 55 additions and 83 deletions

View File

@ -14,14 +14,6 @@ except ImportError:
# It's OK if Django settings aren't configured.
URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
url_re = re.compile(
r'^https?://' # http:// or https://
r'(?:(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}|' #domain...
r'localhost|' #localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|/\S+)$', re.IGNORECASE)
class RegexValidator(object):
regex = ''
message = _(u'Enter a valid value.')
@ -46,7 +38,13 @@ class RegexValidator(object):
raise ValidationError(self.message, code=self.code)
class URLValidator(RegexValidator):
regex = url_re
regex = re.compile(
r'^https?://' # http:// or https://
r'(?:(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}|' #domain...
r'localhost|' #localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|/\S+)$', re.IGNORECASE)
def __init__(self, verify_exists=False, validator_user_agent=URL_VALIDATOR_USER_AGENT):
super(URLValidator, self).__init__()
@ -72,97 +70,70 @@ class URLValidator(RegexValidator):
except: # urllib2.URLError, httplib.InvalidURL, etc.
raise ValidationError(_(u'This URL appears to be a broken link.'), code='invalid_link')
def validate_integer(value):
try:
int(value)
except (ValueError, TypeError), e:
raise ValidationError('')
email_re = re.compile(
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
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):
if not email_re.search(smart_unicode(value)):
raise ValidationError(_(u'Enter a valid e-mail address.'), code='invalid')
validate_email = RegexValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
slug_re = re.compile(r'^[-\w]+$')
def validate_slug(value):
if not slug_re.search(smart_unicode(value)):
raise ValidationError(
_(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."),
code='invalid'
)
validate_slug = RegexValidator(slug_re, _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 'invalid')
ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
def validate_ipv4_address(value):
if not ipv4_re.search(smart_unicode(value)):
raise ValidationError(
_(u'Enter a valid IPv4 address.'),
code="invalid"
)
validate_ipv4_address = RegexValidator(ipv4_re, _(u'Enter a valid IPv4 address.'), 'invalid')
comma_separated_int_list_re = re.compile('^[\d,]+$')
validate_comma_separated_integer_list = RegexValidator(comma_separated_int_list_re, _(u'Enter only digits separated by commas.'), 'invalid')
def validate_comma_separated_integer_list(value):
if not comma_separated_int_list_re.search(smart_unicode(value)):
raise ValidationError(
_(u'Enter only digits separated by commas.'),
code="invalid"
)
class MaxValueValidator(object):
def __init__(self, max_value):
self.max_value = max_value
class BaseValidator(object):
compare = lambda self, a, b: a is b
clean = lambda self, x: x
message = _(u'Ensure this value is %(limit_value)s (it is %(show_value)s).')
code = 'limit_value'
def __init__(self, limit_value):
self.limit_value = limit_value
def __call__(self, value):
if value > self.max_value:
cleaned = self.clean(value)
if self.compare(cleaned, self.limit_value):
raise ValidationError(
_(u'Ensure this value is less than or equal to %s.') % self.max_value,
code='max_value',
params=(self.max_value,)
self.message,
code=self.code,
params={'limit_value': self.limit_value, 'show_value': cleaned}
)
class MinValueValidator(object):
def __init__(self, min_value):
self.min_value = min_value
class MaxValueValidator(BaseValidator):
compare = lambda self, a, b: a > b
message = _(u'Ensure this value is less than or equal to %(limit_value)s.')
code = 'max_value'
def __call__(self, value):
if value < self.min_value:
raise ValidationError(
_(u'Ensure this value is greater than or equal to %s.') % self.min_value,
code='min_value',
params=(self.min_value,)
)
class MinValueValidator(BaseValidator):
compare = lambda self, a, b: a < b
message = _(u'Ensure this value is greater than or equal to %(limit_value)s.')
code = 'min_value'
class MinLengthValidator(object):
def __init__(self, min_length):
self.min_length = min_length
class MinLengthValidator(BaseValidator):
compare = lambda self, a, b: a < b
clean = lambda self, x: len(x)
message = _(u'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).')
code = 'min_length'
def __call__(self, value):
value_len = len(value)
if value_len < self.min_length:
raise ValidationError(
_(u'Ensure this value has at least %(min)d characters (it has %(length)d).'),
code='min_length',
params={ 'min': self.min_length, 'length': value_len}
)
class MaxLengthValidator(BaseValidator):
compare = lambda self, a, b: a > b
clean = lambda self, x: len(x)
message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).')
code = 'max_length'
class MaxLengthValidator(object):
def __init__(self, max_length):
self.max_length = max_length
def __call__(self, value):
value_len = len(value)
if value_len > self.max_length:
raise ValidationError(
_(u'Ensure this value has at most %(max)d characters (it has %(length)d).'),
code='max_length',
params={ 'max': self.max_length, 'length': value_len}
)
class ComplexValidator(object):
def get_value(self, name, all_values, obj):
@ -185,3 +156,4 @@ class RequiredIfOtherFieldBlank(ComplexValidator):
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)

View File

@ -204,8 +204,8 @@ class CharField(Field):
class IntegerField(Field):
default_error_messages = {
'invalid': _(u'Enter a whole number.'),
'max_value': _(u'Ensure this value is less than or equal to %s.'),
'min_value': _(u'Ensure this value is greater than or equal to %s.'),
'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'),
}
def __init__(self, max_value=None, min_value=None, *args, **kwargs):
@ -254,8 +254,8 @@ class FloatField(IntegerField):
class DecimalField(Field):
default_error_messages = {
'invalid': _(u'Enter a number.'),
'max_value': _(u'Ensure this value is less than or equal to %s.'),
'min_value': _(u'Ensure this value is greater than or equal to %s.'),
'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'),
'max_digits': _('Ensure that there are no more than %s digits in total.'),
'max_decimal_places': _('Ensure that there are no more than %s decimal places.'),
'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.')

View File

@ -26,8 +26,8 @@ ValidationError: [u'LENGTH 11, MAX LENGTH 10']
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> e['min_value'] = 'MIN VALUE IS %(limit_value)s'
>>> e['max_value'] = 'MAX VALUE IS %(limit_value)s'
>>> f = IntegerField(min_value=5, max_value=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
@ -50,8 +50,8 @@ ValidationError: [u'MAX VALUE IS 10']
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> e['min_value'] = 'MIN VALUE IS %(limit_value)s'
>>> e['max_value'] = 'MAX VALUE IS %(limit_value)s'
>>> f = FloatField(min_value=5, max_value=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
@ -74,8 +74,8 @@ ValidationError: [u'MAX VALUE IS 10']
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> e['min_value'] = 'MIN VALUE IS %(limit_value)s'
>>> e['max_value'] = 'MAX VALUE IS %(limit_value)s'
>>> e['max_digits'] = 'MAX DIGITS IS %s'
>>> e['max_decimal_places'] = 'MAX DP IS %s'
>>> e['max_whole_digits'] = 'MAX DIGITS BEFORE DP IS %s'