Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit 56ad38a826451c8380c66c074512565d55e7ac53 1 parent 684cf3c
@adrianholovaty adrianholovaty authored
Showing with 240 additions and 9 deletions.
  1. +16 −3 django/newforms/fields.py
  2. +224 −6 tests/regressiontests/forms/tests.py
View
19 django/newforms/fields.py
@@ -76,6 +76,8 @@ def clean(self, value):
of int().
"""
super(IntegerField, self).clean(value)
+ if not self.required and value in EMPTY_VALUES:
+ return u''
try:
return int(value)
except (ValueError, TypeError):
@@ -170,7 +172,9 @@ def clean(self, value):
Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
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)
return value
@@ -246,6 +250,8 @@ def clean(self, value):
value = Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
value = smart_unicode(value)
+ if not self.required and value == u'':
+ return value
valid_values = set([str(k) for k, v in self.choices])
if value not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value)
@@ -259,10 +265,12 @@ def clean(self, value):
"""
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:
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 = []
for val in value:
val = smart_unicode(val)
@@ -277,6 +285,11 @@ def clean(self, value):
class ComboField(Field):
def __init__(self, fields=(), required=True, widget=None):
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
def clean(self, value):
View
230 tests/regressiontests/forms/tests.py
@@ -477,6 +477,22 @@
# 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.clean(1)
u'1'
@@ -518,6 +534,40 @@
# 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')
1
>>> isinstance(f.clean('1'), int)
@@ -681,6 +731,14 @@
...
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 ##################################################################
>>> f = RegexField('^\d[A-F]\d$')
@@ -752,6 +810,34 @@
# 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')
u'person@example.com'
>>> f.clean('foo')
@@ -770,6 +856,48 @@
# 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')
u'http://example.com'
>>> f.clean('http://www.example.com')
@@ -820,6 +948,30 @@
# 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)
True
>>> f.clean(False)
@@ -834,18 +986,32 @@
# ChoiceField #################################################################
>>> f = ChoiceField(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)
u'1'
>>> f.clean('1')
u'1'
->>> f.clean(None)
+>>> f.clean('3')
Traceback (most recent call last):
...
-ValidationError: [u'This field is required.']
+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('')
-Traceback (most recent call last):
-...
-ValidationError: [u'This field is required.']
+u''
+>>> f.clean(None)
+u''
+>>> f.clean(1)
+u'1'
+>>> f.clean('1')
+u'1'
>>> f.clean('3')
Traceback (most recent call last):
...
@@ -862,6 +1028,14 @@
# MultipleChoiceField #########################################################
>>> 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])
[u'1']
>>> f.clean(['1'])
@@ -889,10 +1063,38 @@
...
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 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.clean('test@example.com')
u'test@example.com'
@@ -913,6 +1115,22 @@
...
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 ########################################################################
>>> class Person(Form):
Please sign in to comment.
Something went wrong with that request. Please try again.