Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added unit tests and docs for the newforms case in which the form's d…

…ata doesn't include a value for a nonrequired field

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5218 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 2c86d5728476ba791139e5cef6d0b39c9d83b9f5 1 parent edc014b
Adrian Holovaty authored May 14, 2007
27  docs/newforms.txt
@@ -186,7 +186,7 @@ e-mail address::
186 186
     >>> f.is_valid()
187 187
     False
188 188
 
189  
-Access the ``Form`` attribute ``errors`` to get a dictionary of error messages::
  189
+Access the ``errors`` attribute to get a dictionary of error messages::
190 190
 
191 191
     >>> f.errors
192 192
     {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
@@ -199,6 +199,10 @@ You can access ``errors`` without having to call ``is_valid()`` first. The
199 199
 form's data will be validated the first time either you call ``is_valid()`` or
200 200
 access ``errors``.
201 201
 
  202
+The validation routines will only get called once, regardless of how many times
  203
+you access ``errors`` or call ``is_valid()``. This means that if validation has
  204
+side effects, those side effects will only be triggered once.
  205
+
202 206
 Behavior of unbound forms
203 207
 ~~~~~~~~~~~~~~~~~~~~~~~~~
204 208
 
@@ -276,6 +280,27 @@ but ``clean_data`` contains only the form's fields::
276 280
     >>> f.clean_data # Doesn't contain extra_field_1, etc.
277 281
     {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
278 282
 
  283
+``clean_data`` will include a key and value for *all* fields defined in the
  284
+``Form``, even if the data didn't include a value for fields that are not
  285
+required. In this example, the data dictionary doesn't include a value for the
  286
+``nick_name`` field, but ``clean_data`` includes it, with an empty value::
  287
+
  288
+    >>> class OptionalPersonForm(Form):
  289
+    ...     first_name = CharField()
  290
+    ...     last_name = CharField()
  291
+    ...     nick_name = CharField(required=False)
  292
+    >>> data = {'first_name': u'John', 'last_name': u'Lennon'}
  293
+    >>> f = OptionalPersonForm(data)
  294
+    >>> f.is_valid()
  295
+    True
  296
+    >>> f.clean_data
  297
+    {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
  298
+
  299
+In this above example, the ``clean_data`` value for ``nick_name`` is set to an
  300
+empty string, because ``nick_name`` is ``CharField``, and ``CharField``s treat
  301
+empty values as an empty string. Each field type knows what its "blank" value
  302
+is -- e.g., for ``DateField``, it's ``None`` instead of the empty string.
  303
+
279 304
 Behavior of unbound forms
280 305
 ~~~~~~~~~~~~~~~~~~~~~~~~~
281 306
 
38  tests/regressiontests/forms/tests.py
@@ -1916,6 +1916,34 @@
1916 1916
 >>> p.clean_data
1917 1917
 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
1918 1918
 
  1919
+clean_data will include a key and value for *all* fields defined in the Form,
  1920
+even if the Form's data didn't include a value for fields that are not
  1921
+required. In this example, the data dictionary doesn't include a value for the
  1922
+"nick_name" field, but clean_data includes it. For CharFields, it's set to the
  1923
+empty string.
  1924
+>>> class OptionalPersonForm(Form):
  1925
+...     first_name = CharField()
  1926
+...     last_name = CharField()
  1927
+...     nick_name = CharField(required=False)
  1928
+>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
  1929
+>>> f = OptionalPersonForm(data)
  1930
+>>> f.is_valid()
  1931
+True
  1932
+>>> f.clean_data
  1933
+{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
  1934
+
  1935
+For DateFields, it's set to None.
  1936
+>>> class OptionalPersonForm(Form):
  1937
+...     first_name = CharField()
  1938
+...     last_name = CharField()
  1939
+...     birth_date = DateField(required=False)
  1940
+>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
  1941
+>>> f = OptionalPersonForm(data)
  1942
+>>> f.is_valid()
  1943
+True
  1944
+>>> f.clean_data
  1945
+{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
  1946
+
1919 1947
 "auto_id" tells the Form to add an "id" attribute to each form element.
1920 1948
 If it's a string that contains '%s', Django will use that as a format string
1921 1949
 into which the field's name will be inserted. It will also put a <label> around
@@ -3378,7 +3406,7 @@
3378 3406
 </select>
3379 3407
 
3380 3408
 # MultiWidget and MultiValueField #############################################
3381  
-# MultiWidgets are widgets composed of other widgets. They are usually 
  3409
+# MultiWidgets are widgets composed of other widgets. They are usually
3382 3410
 # combined with MultiValueFields - a field that is composed of other fields.
3383 3411
 # MulitWidgets can themselved be composed of other MultiWidgets.
3384 3412
 # SplitDateTimeWidget is one example of a MultiWidget.
@@ -3386,7 +3414,7 @@
3386 3414
 >>> class ComplexMultiWidget(MultiWidget):
3387 3415
 ...     def __init__(self, attrs=None):
3388 3416
 ...         widgets = (
3389  
-...             TextInput(), 
  3417
+...             TextInput(),
3390 3418
 ...             SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3391 3419
 ...             SplitDateTimeWidget(),
3392 3420
 ...         )
@@ -3411,13 +3439,13 @@
3411 3439
 <input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
3412 3440
 
3413 3441
 >>> class ComplexField(MultiValueField):
3414  
-...     def __init__(self, required=True, widget=None, label=None, initial=None): 
  3442
+...     def __init__(self, required=True, widget=None, label=None, initial=None):
3415 3443
 ...         fields = (
3416  
-...             CharField(), 
  3444
+...             CharField(),
3417 3445
 ...             MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3418 3446
 ...             SplitDateTimeField()
3419 3447
 ...         )
3420  
-...         super(ComplexField, self).__init__(fields, required, widget, label, initial) 
  3448
+...         super(ComplexField, self).__init__(fields, required, widget, label, initial)
3421 3449
 ...
3422 3450
 ...     def compress(self, data_list):
3423 3451
 ...         if data_list:

0 notes on commit 2c86d57

Please sign in to comment.
Something went wrong with that request. Please try again.