newforms: Added a bunch of unit tests and fixed some bugs in the case of required=False for various Field subclasses

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4113 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-11-27 00:49:26 +00:00
parent 684cf3c6fe
commit 56ad38a826
2 changed files with 243 additions and 12 deletions

View File

@ -76,6 +76,8 @@ class IntegerField(Field):
of int(). of int().
""" """
super(IntegerField, self).clean(value) super(IntegerField, self).clean(value)
if not self.required and value in EMPTY_VALUES:
return u''
try: try:
return int(value) return int(value)
except (ValueError, TypeError): except (ValueError, TypeError):
@ -170,7 +172,9 @@ class RegexField(Field):
Field.clean(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
value = smart_unicode(value) value = smart_unicode(value)
if (value or self.required) and not self.regex.search(value): if not self.required and value == u'':
return value
if not self.regex.search(value):
raise ValidationError(self.error_message) raise ValidationError(self.error_message)
return value return value
@ -246,6 +250,8 @@ class ChoiceField(Field):
value = Field.clean(self, value) value = Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
value = smart_unicode(value) value = smart_unicode(value)
if not self.required and value == u'':
return value
valid_values = set([str(k) for k, v in self.choices]) valid_values = set([str(k) for k, v in self.choices])
if value not in valid_values: if value not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value) raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value)
@ -259,10 +265,12 @@ class MultipleChoiceField(ChoiceField):
""" """
Validates that the input is a list or tuple. Validates that the input is a list or tuple.
""" """
if not isinstance(value, (list, tuple)):
raise ValidationError(u'Enter a list of values.')
if self.required and not value: if self.required and not value:
raise ValidationError(u'This field is required.') raise ValidationError(u'This field is required.')
elif not self.required and not value:
return []
if not isinstance(value, (list, tuple)):
raise ValidationError(u'Enter a list of values.')
new_value = [] new_value = []
for val in value: for val in value:
val = smart_unicode(val) val = smart_unicode(val)
@ -277,6 +285,11 @@ class MultipleChoiceField(ChoiceField):
class ComboField(Field): class ComboField(Field):
def __init__(self, fields=(), required=True, widget=None): def __init__(self, fields=(), required=True, widget=None):
Field.__init__(self, required, widget) Field.__init__(self, required, widget)
# Set 'required' to False on the individual fields, because the
# required validation will be handled by ComboField, not by those
# individual fields.
for f in fields:
f.required = False
self.fields = fields self.fields = fields
def clean(self, value): def clean(self, value):

View File

@ -477,6 +477,22 @@ beatle J R Ringo False
# CharField ################################################################### # CharField ###################################################################
>>> f = CharField()
>>> f.clean(1)
u'1'
>>> f.clean('hello')
u'hello'
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean([1, 2, 3])
u'[1, 2, 3]'
>>> f = CharField(required=False) >>> f = CharField(required=False)
>>> f.clean(1) >>> f.clean(1)
u'1' u'1'
@ -518,6 +534,40 @@ u'1234567890a'
# IntegerField ################################################################ # IntegerField ################################################################
>>> f = IntegerField() >>> f = IntegerField()
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('1')
1
>>> isinstance(f.clean('1'), int)
True
>>> f.clean('23')
23
>>> f.clean('a')
Traceback (most recent call last):
...
ValidationError: [u'Enter a whole number.']
>>> f.clean('1 ')
1
>>> f.clean(' 1')
1
>>> f.clean(' 1 ')
1
>>> f.clean('1a')
Traceback (most recent call last):
...
ValidationError: [u'Enter a whole number.']
>>> f = IntegerField(required=False)
>>> f.clean('')
u''
>>> f.clean(None)
u''
>>> f.clean('1') >>> f.clean('1')
1 1
>>> isinstance(f.clean('1'), int) >>> isinstance(f.clean('1'), int)
@ -681,6 +731,14 @@ Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date/time.'] ValidationError: [u'Enter a valid date/time.']
>>> f = DateTimeField(required=False)
>>> f.clean(None)
>>> repr(f.clean(None))
'None'
>>> f.clean('')
>>> repr(f.clean(''))
'None'
# RegexField ################################################################## # RegexField ##################################################################
>>> f = RegexField('^\d[A-F]\d$') >>> f = RegexField('^\d[A-F]\d$')
@ -752,6 +810,34 @@ ValidationError: [u'Enter a four-digit number.']
# EmailField ################################################################## # EmailField ##################################################################
>>> f = EmailField() >>> f = EmailField()
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('person@example.com')
u'person@example.com'
>>> f.clean('foo')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid e-mail address.']
>>> f.clean('foo@')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid e-mail address.']
>>> f.clean('foo@bar')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid e-mail address.']
>>> f = EmailField(required=False)
>>> f.clean('')
u''
>>> f.clean(None)
u''
>>> f.clean('person@example.com') >>> f.clean('person@example.com')
u'person@example.com' u'person@example.com'
>>> f.clean('foo') >>> f.clean('foo')
@ -770,6 +856,48 @@ ValidationError: [u'Enter a valid e-mail address.']
# URLField ################################################################## # URLField ##################################################################
>>> f = URLField() >>> f = URLField()
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('http://example.com')
u'http://example.com'
>>> f.clean('http://www.example.com')
u'http://www.example.com'
>>> f.clean('foo')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('example.com')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://example')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://example.')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://.com')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f = URLField(required=False)
>>> f.clean('')
u''
>>> f.clean(None)
u''
>>> f.clean('http://example.com') >>> f.clean('http://example.com')
u'http://example.com' u'http://example.com'
>>> f.clean('http://www.example.com') >>> f.clean('http://www.example.com')
@ -820,6 +948,30 @@ ValidationError: [u'This URL appears to be a broken link.']
# BooleanField ################################################################ # BooleanField ################################################################
>>> f = BooleanField() >>> f = BooleanField()
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(True)
True
>>> f.clean(False)
False
>>> f.clean(1)
True
>>> f.clean(0)
False
>>> f.clean('Django rocks')
True
>>> f = BooleanField(required=False)
>>> f.clean('')
False
>>> f.clean(None)
False
>>> f.clean(True) >>> f.clean(True)
True True
>>> f.clean(False) >>> f.clean(False)
@ -834,18 +986,32 @@ True
# ChoiceField ################################################################# # ChoiceField #################################################################
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) >>> f = ChoiceField(choices=[('1', '1'), ('2', '2')])
>>> f.clean(1)
u'1'
>>> f.clean('1')
u'1'
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('') >>> f.clean('')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'This field is required.'] ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(1)
u'1'
>>> f.clean('1')
u'1'
>>> f.clean('3')
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
>>> f.clean('')
u''
>>> f.clean(None)
u''
>>> f.clean(1)
u'1'
>>> f.clean('1')
u'1'
>>> f.clean('3') >>> f.clean('3')
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -862,6 +1028,14 @@ ValidationError: [u'Select a valid choice. John is not one of the available choi
# MultipleChoiceField ######################################################### # MultipleChoiceField #########################################################
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')]) >>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')])
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean([1]) >>> f.clean([1])
[u'1'] [u'1']
>>> f.clean(['1']) >>> f.clean(['1'])
@ -889,10 +1063,38 @@ Traceback (most recent call last):
... ...
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
>>> f.clean('')
[]
>>> f.clean(None)
[]
>>> f.clean([1])
[u'1']
>>> f.clean(['1'])
[u'1']
>>> f.clean(['1', '2'])
[u'1', u'2']
>>> f.clean([1, '2'])
[u'1', u'2']
>>> f.clean((1, '2'))
[u'1', u'2']
>>> f.clean('hello')
Traceback (most recent call last):
...
ValidationError: [u'Enter a list of values.']
>>> f.clean([])
[]
>>> f.clean(())
[]
>>> f.clean(['3'])
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
# ComboField ################################################################## # ComboField ##################################################################
ComboField takes a list of fields that should be used to validate a value, ComboField takes a list of fields that should be used to validate a value,
in that order: in that order.
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) >>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
>>> f.clean('test@example.com') >>> f.clean('test@example.com')
u'test@example.com' u'test@example.com'
@ -913,6 +1115,22 @@ Traceback (most recent call last):
... ...
ValidationError: [u'This field is required.'] ValidationError: [u'This field is required.']
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False)
>>> f.clean('test@example.com')
u'test@example.com'
>>> f.clean('longemailaddress@example.com')
Traceback (most recent call last):
...
ValidationError: [u'Ensure this value has at most 20 characters.']
>>> f.clean('not an e-mail')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid e-mail address.']
>>> f.clean('')
u''
>>> f.clean(None)
u''
# Form ######################################################################## # Form ########################################################################
>>> class Person(Form): >>> class Person(Form):