Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added a lot more to docs/newforms.txt

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4288 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 84b673e9b1e17b27c3003ca4cc14c90cda8274b3 1 parent 13184ef
Adrian Holovaty authored January 05, 2007

Showing 1 changed file with 319 additions and 104 deletions. Show diff stats Hide diff stats

  1. 423  docs/newforms.txt
423  docs/newforms.txt
@@ -2,9 +2,9 @@
2 2
 The newforms library
3 3
 ====================
4 4
 
5  
-``django.newforms`` is a new replacement for ``django.forms``, the old Django
6  
-form/manipulator/validation framework. This document explains how to use this
7  
-new form library.
  5
+``django.newforms`` is Django's fantastic new form-handling library. It's a
  6
+replacement for ``django.forms``, the old form/manipulator/validation
  7
+framework. This document explains how to use this new library.
8 8
 
9 9
 Migration plan
10 10
 ==============
@@ -103,10 +103,10 @@ fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. We'll explain
103 103
 the different types of fields -- e.g., ``CharField`` and ``EmailField`` --
104 104
 shortly.
105 105
 
106  
-Creating form instances
107  
------------------------
  106
+Creating ``Form`` instances
  107
+---------------------------
108 108
 
109  
-A form instance is either **bound** or **unbound** to a set of data.
  109
+A ``Form`` instance is either **bound** or **unbound** to a set of data.
110 110
 
111 111
     * If it's **bound** to a set of data, it's capable of validating that data
112 112
       and rendering the form as HTML with the data displayed in the HTML.
@@ -114,7 +114,7 @@ A form instance is either **bound** or **unbound** to a set of data.
114 114
     * If it's **unbound**, it cannot do validation (because there's no data to
115 115
       validate!), but it can still render the blank form as HTML.
116 116
 
117  
-To create an unbound form instance, simply instantiate the class::
  117
+To create an unbound ``Form`` instance, simply instantiate the class::
118 118
 
119 119
     >>> f = ContactForm()
120 120
 
@@ -155,11 +155,122 @@ if you want to bind an unbound ``Form`` instance to some data, create another
155 155
 a ``Form`` instance has been created, you should consider its data immutable,
156 156
 whether it has data or not.
157 157
 
  158
+Using forms to validate data
  159
+----------------------------
  160
+
  161
+The primary task of a ``Form`` object is to validate data. With a bound
  162
+``Form`` instance, call the ``is_valid()`` method to run validation and return
  163
+a boolean designating whether the data was valid::
  164
+
  165
+    >>> data = {'subject': 'hello',
  166
+    ...         'message': 'Hi there',
  167
+    ...         'sender': 'foo@example.com',
  168
+    ...         'cc_myself': True}
  169
+    >>> f = ContactForm(data)
  170
+    >>> f.is_valid()
  171
+    True
  172
+
  173
+Let's try with some invalid data. In this case, ``subject`` is blank (an error,
  174
+because all fields are required by default) and ``sender`` is not a valid
  175
+e-mail address::
  176
+
  177
+    >>> data = {'subject': '',
  178
+    ...         'message': 'Hi there',
  179
+    ...         'sender': 'invalid e-mail address',
  180
+    ...         'cc_myself': True}
  181
+    >>> f = ContactForm(data)
  182
+    >>> f.is_valid()
  183
+    False
  184
+
  185
+Access the ``Form`` attribute ``errors`` to get a dictionary of error messages::
  186
+
  187
+    >>> f.errors
  188
+    {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
  189
+
  190
+In this dictionary, the keys are the field names, and the values are lists of
  191
+Unicode strings representing the error messages. The error messages are stored
  192
+in lists because a field can have multiple error messages.
  193
+
  194
+You can access ``errors`` without having to call ``is_valid()`` first. The
  195
+form's data will be validated the first time either you call ``is_valid()`` or
  196
+access ``errors``.
  197
+
  198
+Behavior of unbound forms
  199
+~~~~~~~~~~~~~~~~~~~~~~~~~
  200
+
  201
+It's meaningless to validate a form with no data, but, for the record, here's
  202
+what happens with unbound forms::
  203
+
  204
+    >>> f = ContactForm()
  205
+    >>> f.is_valid()
  206
+    False
  207
+    >>> f.errors
  208
+    {}
  209
+
  210
+Accessing "clean" data
  211
+----------------------
  212
+
  213
+Each ``Field`` in a ``Form`` class is responsible not only for validating data,
  214
+but also for "cleaning" it -- normalizing it to a consistent format. This is a
  215
+nice feature, because it allows data for a particular field to be input in
  216
+a variety of ways, always resulting in consistent output.
  217
+
  218
+For example, ``DateField`` normalizes input into a Python ``datetime.date``
  219
+object. Regardless of whether you pass it a string in the format
  220
+``'1994-07-15'``, a ``datetime.date`` object or a number of other formats,
  221
+``DateField`` will always normalize it to a ``datetime.date`` object as long as
  222
+it's valid.
  223
+
  224
+Once you've created a ``Form`` instance with a set of data and validated it,
  225
+you can access the clean data via the ``clean_data`` attribute of the ``Form``
  226
+object::
  227
+
  228
+    >>> data = {'subject': 'hello',
  229
+    ...         'message': 'Hi there',
  230
+    ...         'sender': 'foo@example.com',
  231
+    ...         'cc_myself': True}
  232
+    >>> f = ContactForm(data)
  233
+    >>> f.is_valid()
  234
+    True
  235
+    >>> f.clean_data
  236
+    {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
  237
+
  238
+Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
  239
+always cleans the input into a Unicode string. We'll cover the encoding
  240
+implications later in this document.
  241
+
  242
+If your data does *not* validate, your ``Form`` instance will not have a
  243
+``clean_data`` attribute::
  244
+
  245
+    >>> data = {'subject': '',
  246
+    ...         'message': 'Hi there',
  247
+    ...         'sender': 'invalid e-mail address',
  248
+    ...         'cc_myself': True}
  249
+    >>> f = ContactForm(data)
  250
+    >>> f.is_valid()
  251
+    False
  252
+    >>> f.clean_data
  253
+    Traceback (most recent call last):
  254
+    ...
  255
+    AttributeError: 'ContactForm' object has no attribute 'clean_data'
  256
+
  257
+Behavior of unbound forms
  258
+~~~~~~~~~~~~~~~~~~~~~~~~~
  259
+
  260
+It's meaningless to request "clean" data in a form with no data, but, for the
  261
+record, here's what happens with unbound forms::
  262
+
  263
+    >>> f = ContactForm()
  264
+    >>> f.clean_data
  265
+    Traceback (most recent call last):
  266
+    ...
  267
+    AttributeError: 'ContactForm' object has no attribute 'clean_data'
  268
+
158 269
 Outputting forms as HTML
159 270
 ------------------------
160 271
 
161  
-The first thing we can do with a form is output it as HTML. To do so, instantiate
162  
-it and ``print`` it.
  272
+The second task of a ``Form`` object is to render itself as HTML. To do so,
  273
+simply ``print`` it::
163 274
 
164 275
     >>> f = ContactForm()
165 276
     >>> print f
@@ -357,6 +468,37 @@ example, in the ``ContactForm`` example, the fields are defined in the order
357 468
 ``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
358 469
 output, just change the order in which those fields are listed in the class.
359 470
 
  471
+How errors are displayed
  472
+~~~~~~~~~~~~~~~~~~~~~~~~
  473
+
  474
+If you render a bound ``Form`` object, the act of rendering will automatically
  475
+run the form's validation if it hasn't already happened, and the HTML output
  476
+will include the validation errors as a ``<ul>`` near the field. The particular
  477
+positioning of the error messages depends on the output method you're using::
  478
+
  479
+    >>> data = {'subject': '',
  480
+    ...         'message': 'Hi there',
  481
+    ...         'sender': 'invalid e-mail address',
  482
+    ...         'cc_myself': True}
  483
+    >>> f = ContactForm(data, auto_id=False)
  484
+    >>> print f.as_table()
  485
+    <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
  486
+    <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
  487
+    <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr>
  488
+    <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
  489
+    >>> print f.as_ul()
  490
+    <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
  491
+    <li>Message: <input type="text" name="message" value="Hi there" /></li>
  492
+    <li><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li>
  493
+    <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
  494
+    >>> print f.as_p()
  495
+    <p><ul class="errorlist"><li>This field is required.</li></ul></p>
  496
+    <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
  497
+    <p>Message: <input type="text" name="message" value="Hi there" /></p>
  498
+    <p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p>
  499
+    <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
  500
+    <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
  501
+
360 502
 More granular output
361 503
 ~~~~~~~~~~~~~~~~~~~~
362 504
 
@@ -393,116 +535,186 @@ The field-specific output honors the form object's ``auto_id`` setting::
393 535
     >>> print f['message']
394 536
     <input type="text" name="message" id="id_message" />
395 537
 
396  
-Using forms to validate data
397  
-----------------------------
  538
+For a field's list of errors, access the field's ``errors`` attribute. This
  539
+is a list-like object that is displayed as an HTML ``<ul>`` when printed::
398 540
 
399  
-In addition to HTML form display, a ``Form`` class is responsible for
400  
-validating data. With a bound ``Form`` instance, call the ``is_valid()``
401  
-method to run validation and return a boolean designating whether the data was
402  
-valid::
  541
+    >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
  542
+    >>> f = ContactForm(data, auto_id=False)
  543
+    >>> print f['message']
  544
+    <input type="text" name="message" />
  545
+    >>> f['message'].errors
  546
+    [u'This field is required.']
  547
+    >>> print f['message'].errors
  548
+    <ul class="errorlist"><li>This field is required.</li></ul>
  549
+    >>> f['subject'].errors
  550
+    []
  551
+    >>> print f['subject'].errors
  552
+
  553
+    >>> str(f['subject'].errors)
  554
+    ''
  555
+
  556
+Fields
  557
+======
  558
+
  559
+When you create a ``Form`` class, the most important part is defining the
  560
+fields of the form. Each field has custom validation logic, along with a few
  561
+other hooks.
  562
+
  563
+Although the primary way you'll use ``Field`` classes is in ``Form`` classes,
  564
+you can also instantiate them and use them directly to get a better idea of
  565
+how they work. Each ``Field`` instance has a ``clean()`` method, which takes
  566
+a single argument and either raises a ``django.newforms.ValidationError``
  567
+exception or returns the clean value::
  568
+
  569
+    >>> f = forms.EmailField()
  570
+    >>> f.clean('foo@example.com')
  571
+    u'foo@example.com'
  572
+    >>> f.clean(u'foo@example.com')
  573
+    u'foo@example.com'
  574
+    >>> f.clean('invalid e-mail address')
  575
+    Traceback (most recent call last):
  576
+    ...
  577
+    ValidationError: [u'Enter a valid e-mail address.']
403 578
 
404  
-    >>> data = {'subject': 'hello',
405  
-    ...         'message': 'Hi there',
406  
-    ...         'sender': 'foo@example.com',
407  
-    ...         'cc_myself': True}
408  
-    >>> f = ContactForm(data)
409  
-    >>> f.is_valid()
410  
-    True
  579
+Core field arguments
  580
+--------------------
411 581
 
412  
-Let's try with some invalid data. In this case, ``subject`` is blank (an error,
413  
-because all fields are required by default) and ``sender`` is not a valid
414  
-e-mail address::
  582
+Each ``Field`` class constructor takes at least these arguments. Some
  583
+``Field`` classes take additional, field-specific arguments, but the following
  584
+should *always* be available:
415 585
 
416  
-    >>> data = {'subject': '',
417  
-    ...         'message': 'Hi there',
418  
-    ...         'sender': 'invalid e-mail address',
419  
-    ...         'cc_myself': True}
420  
-    >>> f = ContactForm(data)
421  
-    >>> f.is_valid()
422  
-    False
  586
+``required``
  587
+~~~~~~~~~~~~
423 588
 
424  
-Access the ``Form`` attribute ``errors`` to get a dictionary of error messages::
  589
+By default, each ``Field`` class assumes the value is required, so if you pass
  590
+an empty value -- either ``None`` or the empty string (``""``) -- then
  591
+``clean()`` will raise a ``ValidationError`` exception::
425 592
 
426  
-    >>> f.errors
427  
-    {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
  593
+    >>> f = forms.CharField()
  594
+    >>> f.clean('foo')
  595
+    u'foo'
  596
+    >>> f.clean('')
  597
+    Traceback (most recent call last):
  598
+    ...
  599
+    ValidationError: [u'This field is required.']
  600
+    >>> f.clean(None)
  601
+    Traceback (most recent call last):
  602
+    ...
  603
+    ValidationError: [u'This field is required.']
  604
+    >>> f.clean(' ')
  605
+    u' '
  606
+    >>> f.clean(0)
  607
+    u'0'
  608
+    >>> f.clean(True)
  609
+    u'True'
  610
+    >>> f.clean(False)
  611
+    u'False'
  612
+
  613
+To specify that a field is *not* required, pass ``required=False`` to the
  614
+``Field`` constructor::
  615
+
  616
+    >>> f = forms.CharField(required=False)
  617
+    >>> f.clean('foo')
  618
+    u'foo'
  619
+    >>> f.clean('')
  620
+    u''
  621
+    >>> f.clean(None)
  622
+    u''
  623
+    >>> f.clean(0)
  624
+    u'0'
  625
+    >>> f.clean(True)
  626
+    u'True'
  627
+    >>> f.clean(False)
  628
+    u'False'
  629
+
  630
+If a ``Field`` has ``required=False`` and you pass ``clean()`` an empty value,
  631
+then ``clean()`` will return a *normalized* empty value rather than raising
  632
+``ValidationError``. For ``CharField``, this will be a Unicode empty string.
  633
+For other ``Field`` classes, it might be ``None``. (This varies from field to
  634
+field.)
  635
+
  636
+``label``
  637
+~~~~~~~~~
  638
+
  639
+The ``label`` argument lets you specify the "human-friendly" label for this
  640
+field. This is used when the ``Field`` is displayed in a ``Form``.
  641
+
  642
+As explained in _`Outputting forms as HTML` above, the default label for a
  643
+``Field`` is generated from the field name by converting all underscores to
  644
+spaces and upper-casing the first letter. Specify ``label`` if that default
  645
+behavior doesn't result in an adequate label.
  646
+
  647
+Here's a full example ``Form`` that implements ``label`` for two of its fields.
  648
+We've specified ``auto_id=False`` to simplify the output::
  649
+
  650
+    >>> class CommentForm(forms.Form):
  651
+    ...     name = forms.CharField(label='Your name')
  652
+    ...     url = forms.URLField(label='Your Web site', required=False)
  653
+    ...     comment = forms.CharField()
  654
+    >>> f = CommentForm(auto_id=False)
  655
+    >>> print f
  656
+    <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
  657
+    <tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr>
  658
+    <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
428 659
 
429  
-In this dictionary, the keys are the field names, and the values are lists of
430  
-Unicode strings representing the error messages.
  660
+``initial``
  661
+~~~~~~~
431 662
 
432  
-You can access ``errors`` without having to call ``is_valid()`` first. The
433  
-form's data will be validated the first time either you call ``is_valid()`` or
434  
-access ``errors``.
  663
+The ``initial`` argument lets you specify the initial value to use when
  664
+rendering this ``Field`` in an unbound ``Form``.
435 665
 
436  
-Behavior of unbound forms
437  
-~~~~~~~~~~~~~~~~~~~~~~~~~
  666
+The use-case for this is when you want to display an "empty" form in which a
  667
+field is initialized to a particular value. For example::
438 668
 
439  
-It's meaningless to validate a form with no data, but, for the record, here's
440  
-what happens with unbound forms::
441  
-
442  
-    >>> f = ContactForm()
  669
+    >>> class CommentForm(forms.Form):
  670
+    ...     name = forms.CharField(initial='Your name')
  671
+    ...     url = forms.URLField(initial='http://')
  672
+    ...     comment = forms.CharField()
  673
+    >>> f = CommentForm(auto_id=False)
  674
+    >>> print f
  675
+    <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
  676
+    <tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr>
  677
+    <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
  678
+
  679
+You may be thinking, why not just pass a dictionary of the initial values as
  680
+data when displaying the form? Well, if you do that, you'll trigger validation,
  681
+and the HTML output will include any validation errors::
  682
+
  683
+    >>> class CommentForm(forms.Form):
  684
+    ...     name = forms.CharField()
  685
+    ...     url = forms.URLField()
  686
+    ...     comment = forms.CharField()
  687
+    >>> default_data = {'name': 'Your name', 'url': 'http://'}
  688
+    >>> f = CommentForm(default_data, auto_id=False)
  689
+    >>> print f
  690
+    <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
  691
+    <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr>
  692
+    <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
  693
+
  694
+This is why ``initial`` values are only displayed for unbound forms. For bound
  695
+forms, the HTML output will use the bound data.
  696
+
  697
+Also note that ``initial`` values are *not* used as "fallback" data in
  698
+validation if a particular field's value is not given. ``initial`` values are
  699
+*only* intended for initial form display::
  700
+
  701
+    >>> class CommentForm(forms.Form):
  702
+    ...     name = forms.CharField(initial='Your name')
  703
+    ...     url = forms.URLField(initial='http://')
  704
+    ...     comment = forms.CharField()
  705
+    >>> data = {'name': '', 'url': '', 'comment': 'Foo'}
  706
+    >>> f = CommentForm(data)
443 707
     >>> f.is_valid()
444 708
     False
  709
+    # The form does *not* fall back to using the initial values.
445 710
     >>> f.errors
446  
-    {}
447  
-
448  
-Accessing "clean" data
449  
-----------------------
450  
-
451  
-Each ``Field`` in a ``Form`` class is responsible not only for validating data,
452  
-but also for "cleaning" it -- normalizing it to a consistent format. This is a
453  
-nice feature, because it allows data for a particular field to be input in
454  
-a variety of ways, always resulting in consistent output.
455  
-
456  
-For example, ``DateField`` normalizes input into a Python ``datetime.date``
457  
-object. Regardless of whether you pass it a string in the format
458  
-``'1994-07-15'``, a ``datetime.date`` object or a number of other formats,
459  
-``DateField`` will always normalize it to a ``datetime.date`` object as long as
460  
-it's valid.
461  
-
462  
-Once you've created a ``Form`` instance with a set of data and validated it,
463  
-you can access the clean data via the ``clean_data`` attribute of the ``Form``
464  
-object::
465  
-
466  
-    >>> data = {'subject': 'hello',
467  
-    ...         'message': 'Hi there',
468  
-    ...         'sender': 'foo@example.com',
469  
-    ...         'cc_myself': True}
470  
-    >>> f = ContactForm(data)
471  
-    >>> f.is_valid()
472  
-    True
473  
-    >>> f.clean_data
474  
-    {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
475  
-
476  
-Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
477  
-always cleans the input into a Unicode string. We'll cover the encoding
478  
-implications later in this document.
  711
+    {'url': [u'This field is required.'], 'name': [u'This field is required.']}
479 712
 
480  
-If your data does *not* validate, your ``Form`` instance will not have a
481  
-``clean_data`` attribute::
482  
-
483  
-    >>> data = {'subject': '',
484  
-    ...         'message': 'Hi there',
485  
-    ...         'sender': 'invalid e-mail address',
486  
-    ...         'cc_myself': True}
487  
-    >>> f = ContactForm(data)
488  
-    >>> f.is_valid()
489  
-    False
490  
-    >>> f.clean_data
491  
-    Traceback (most recent call last):
492  
-    ...
493  
-    AttributeError: 'ContactForm' object has no attribute 'clean_data'
  713
+``widget``
  714
+~~~~~~~~~~
494 715
 
495  
-Behavior of unbound forms
496  
-~~~~~~~~~~~~~~~~~~~~~~~~~
497  
-
498  
-It's meaningless to request "clean" data in a form with no data, but, for the
499  
-record, here's what happens with unbound forms::
500  
-
501  
-    >>> f = ContactForm()
502  
-    >>> f.clean_data
503  
-    Traceback (most recent call last):
504  
-    ...
505  
-    AttributeError: 'ContactForm' object has no attribute 'clean_data'
  716
+The ``widget`` argument lets you specify a ``Widget`` class to use when
  717
+rendering this ``Field``. See _`Widgets` below for more information.
506 718
 
507 719
 More coming soon
508 720
 ================
@@ -514,3 +726,6 @@ what's possible.
514 726
 
515 727
 If you're really itching to learn and use this library, please be patient.
516 728
 We're working hard on finishing both the code and documentation.
  729
+
  730
+Widgets
  731
+=======

0 notes on commit 84b673e

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