2101 lines
90 KiB
Plaintext
2101 lines
90 KiB
Plaintext
====================
|
|
The newforms library
|
|
====================
|
|
|
|
``django.newforms`` is Django's fantastic new form-handling library. It's a
|
|
replacement for ``django.forms``, the old form/manipulator/validation
|
|
framework. This document explains how to use this new library.
|
|
|
|
Migration plan
|
|
==============
|
|
|
|
``django.newforms`` is new in Django's 0.96 release, but, as it won't be new
|
|
forever, we plan to rename it to ``django.forms`` in the future. The current
|
|
``django.forms`` package will be available as ``django.oldforms`` until Django
|
|
1.0, when we plan to remove it for good.
|
|
|
|
That has direct repercussions on the forward compatibility of your code. Please
|
|
read the following migration plan and code accordingly:
|
|
|
|
* The old forms framework (the current ``django.forms``) has been copied to
|
|
``django.oldforms``. Thus, you can start upgrading your code *now*,
|
|
rather than waiting for the future backwards-incompatible change, by
|
|
changing your import statements like this::
|
|
|
|
from django import forms # old
|
|
from django import oldforms as forms # new
|
|
|
|
* In the next Django release (0.97), we will move the current
|
|
``django.newforms`` to ``django.forms``. This will be a
|
|
backwards-incompatible change, and anybody who is still using the old
|
|
version of ``django.forms`` at that time will need to change their import
|
|
statements, as described in the previous bullet.
|
|
|
|
* We will remove ``django.oldforms`` in the release *after* the next Django
|
|
release -- either 0.98 or 1.0, whichever comes first.
|
|
|
|
With this in mind, we recommend you use the following import statement when
|
|
using ``django.newforms``::
|
|
|
|
from django import newforms as forms
|
|
|
|
This way, your code can refer to the ``forms`` module, and when
|
|
``django.newforms`` is renamed to ``django.forms``, you'll only have to change
|
|
your ``import`` statements.
|
|
|
|
If you prefer "``import *``" syntax, you can do the following::
|
|
|
|
from django.newforms import *
|
|
|
|
This will import all fields, widgets, form classes and other various utilities
|
|
into your local namespace. Some people find this convenient; others find it
|
|
too messy. The choice is yours.
|
|
|
|
Overview
|
|
========
|
|
|
|
As with the ``django.forms`` ("manipulators") system before it,
|
|
``django.newforms`` is intended to handle HTML form display, data processing
|
|
(validation) and redisplay. It's what you use if you want to perform
|
|
server-side validation for an HTML form.
|
|
|
|
For example, if your Web site has a contact form that visitors can use to
|
|
send you e-mail, you'd use this library to implement the display of the HTML
|
|
form fields, along with the form validation. Any time you need to use an HTML
|
|
``<form>``, you can use this library.
|
|
|
|
The library deals with these concepts:
|
|
|
|
* **Widget** -- A class that corresponds to an HTML form widget, e.g.
|
|
``<input type="text">`` or ``<textarea>``. This handles rendering of the
|
|
widget as HTML.
|
|
|
|
* **Field** -- A class that is responsible for doing validation, e.g.
|
|
an ``EmailField`` that makes sure its data is a valid e-mail address.
|
|
|
|
* **Form** -- A collection of fields that knows how to validate itself and
|
|
display itself as HTML.
|
|
|
|
The library is decoupled from the other Django components, such as the database
|
|
layer, views and templates. It relies only on Django settings, a couple of
|
|
``django.utils`` helper functions and Django's internationalization hooks (but
|
|
you're not required to be using internationalization features to use this
|
|
library).
|
|
|
|
Form objects
|
|
============
|
|
|
|
The primary way of using the ``newforms`` library is to create a form object.
|
|
Do this by subclassing ``django.newforms.Form`` and specifying the form's
|
|
fields, in a declarative style that you'll be familiar with if you've used
|
|
Django database models. In this section, we'll iteratively develop a form
|
|
object that you might use to implement "contact me" functionality on your
|
|
personal Web site.
|
|
|
|
Start with this basic ``Form`` subclass, which we'll call ``ContactForm``::
|
|
|
|
from django import newforms as forms
|
|
|
|
class ContactForm(forms.Form):
|
|
subject = forms.CharField(max_length=100)
|
|
message = forms.CharField()
|
|
sender = forms.EmailField()
|
|
cc_myself = forms.BooleanField()
|
|
|
|
A form is composed of ``Field`` objects. In this case, our form has four
|
|
fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. We'll explain
|
|
the different types of fields -- e.g., ``CharField`` and ``EmailField`` --
|
|
shortly.
|
|
|
|
Creating ``Form`` instances
|
|
---------------------------
|
|
|
|
A ``Form`` instance is either **bound** to a set of data, or **unbound**.
|
|
|
|
* If it's **bound** to a set of data, it's capable of validating that data
|
|
and rendering the form as HTML with the data displayed in the HTML.
|
|
|
|
* If it's **unbound**, it cannot do validation (because there's no data to
|
|
validate!), but it can still render the blank form as HTML.
|
|
|
|
To create an unbound ``Form`` instance, simply instantiate the class::
|
|
|
|
>>> f = ContactForm()
|
|
|
|
To bind data to a form, pass the data as a dictionary as the first parameter to
|
|
your ``Form`` class constructor::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
|
|
In this dictionary, the keys are the field names, which correspond to the
|
|
attributes in your ``Form`` class. The values are the data you're trying
|
|
to validate. These will usually be strings, but there's no requirement that
|
|
they be strings; the type of data you pass depends on the ``Field``, as we'll
|
|
see in a moment.
|
|
|
|
If you need to distinguish between bound and unbound form instances at runtime,
|
|
check the value of the form's ``is_bound`` attribute::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.is_bound
|
|
False
|
|
>>> f = ContactForm({'subject': 'hello'})
|
|
>>> f.is_bound
|
|
True
|
|
|
|
Note that passing an empty dictionary creates a *bound* form with empty data::
|
|
|
|
>>> f = ContactForm({})
|
|
>>> f.is_bound
|
|
True
|
|
|
|
If you have a bound ``Form`` instance and want to change the data somehow, or
|
|
if you want to bind an unbound ``Form`` instance to some data, create another
|
|
``Form`` instance. There is no way to change data in a ``Form`` instance. Once
|
|
a ``Form`` instance has been created, you should consider its data immutable,
|
|
whether it has data or not.
|
|
|
|
Using forms to validate data
|
|
----------------------------
|
|
|
|
The primary task of a ``Form`` object is to validate data. With a bound
|
|
``Form`` instance, call the ``is_valid()`` method to run validation and return
|
|
a boolean designating whether the data was valid::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
|
|
Let's try with some invalid data. In this case, ``subject`` is blank (an error,
|
|
because all fields are required by default) and ``sender`` is not a valid
|
|
e-mail address::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid e-mail address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
False
|
|
|
|
Access the ``errors`` attribute to get a dictionary of error messages::
|
|
|
|
>>> f.errors
|
|
{'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
|
|
|
|
In this dictionary, the keys are the field names, and the values are lists of
|
|
Unicode strings representing the error messages. The error messages are stored
|
|
in lists because a field can have multiple error messages.
|
|
|
|
You can access ``errors`` without having to call ``is_valid()`` first. The
|
|
form's data will be validated the first time either you call ``is_valid()`` or
|
|
access ``errors``.
|
|
|
|
The validation routines will only get called once, regardless of how many times
|
|
you access ``errors`` or call ``is_valid()``. This means that if validation has
|
|
side effects, those side effects will only be triggered once.
|
|
|
|
Behavior of unbound forms
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It's meaningless to validate a form with no data, but, for the record, here's
|
|
what happens with unbound forms::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.is_valid()
|
|
False
|
|
>>> f.errors
|
|
{}
|
|
|
|
Accessing "clean" data
|
|
----------------------
|
|
|
|
Each ``Field`` in a ``Form`` class is responsible not only for validating data,
|
|
but also for "cleaning" it -- normalizing it to a consistent format. This is a
|
|
nice feature, because it allows data for a particular field to be input in
|
|
a variety of ways, always resulting in consistent output.
|
|
|
|
For example, ``DateField`` normalizes input into a Python ``datetime.date``
|
|
object. Regardless of whether you pass it a string in the format
|
|
``'1994-07-15'``, a ``datetime.date`` object or a number of other formats,
|
|
``DateField`` will always normalize it to a ``datetime.date`` object as long as
|
|
it's valid.
|
|
|
|
Once you've created a ``Form`` instance with a set of data and validated it,
|
|
you can access the clean data via the ``cleaned_data`` attribute of the ``Form``
|
|
object::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data
|
|
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
|
|
|
|
Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
|
|
always cleans the input into a Unicode string. We'll cover the encoding
|
|
implications later in this document.
|
|
|
|
If your data does *not* validate, your ``Form`` instance will not have a
|
|
``cleaned_data`` attribute::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid e-mail address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
False
|
|
>>> f.cleaned_data
|
|
Traceback (most recent call last):
|
|
...
|
|
AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
|
|
|
|
``cleaned_data`` will always *only* contain a key for fields defined in the
|
|
``Form``, even if you pass extra data when you define the ``Form``. In this
|
|
example, we pass a bunch of extra fields to the ``ContactForm`` constructor,
|
|
but ``cleaned_data`` contains only the form's fields::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True,
|
|
... 'extra_field_1': 'foo',
|
|
... 'extra_field_2': 'bar',
|
|
... 'extra_field_3': 'baz'}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data # Doesn't contain extra_field_1, etc.
|
|
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
|
|
|
|
``cleaned_data`` will include a key and value for *all* fields defined in the
|
|
``Form``, even if the data didn't include a value for fields that are not
|
|
required. In this example, the data dictionary doesn't include a value for the
|
|
``nick_name`` field, but ``cleaned_data`` includes it, with an empty value::
|
|
|
|
>>> class OptionalPersonForm(Form):
|
|
... first_name = CharField()
|
|
... last_name = CharField()
|
|
... nick_name = CharField(required=False)
|
|
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
|
|
>>> f = OptionalPersonForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data
|
|
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
|
|
|
|
In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an
|
|
empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat
|
|
empty values as an empty string. Each field type knows what its "blank" value
|
|
is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For
|
|
full details on each field's behavior in this case, see the "Empty value" note
|
|
for each field in the "Built-in ``Field`` classes" section below.
|
|
|
|
You can write code to perform validation for particular form fields (based on
|
|
their name) or for the form as a whole (considering combinations of various
|
|
fields). More information about this is in the `Custom form and field
|
|
validation`_ section, below.
|
|
|
|
Behavior of unbound forms
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It's meaningless to request "cleaned" data in a form with no data, but, for the
|
|
record, here's what happens with unbound forms::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.cleaned_data
|
|
Traceback (most recent call last):
|
|
...
|
|
AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
|
|
|
|
Outputting forms as HTML
|
|
------------------------
|
|
|
|
The second task of a ``Form`` object is to render itself as HTML. To do so,
|
|
simply ``print`` it::
|
|
|
|
>>> f = ContactForm()
|
|
>>> print f
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
|
|
|
|
If the form is bound to data, the HTML output will include that data
|
|
appropriately. For example, if a field is represented by an
|
|
``<input type="text">``, the data will be in the ``value`` attribute. If a
|
|
field is represented by an ``<input type="checkbox">``, then that HTML will
|
|
include ``checked="checked"`` if appropriate::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> print f
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>
|
|
|
|
This default output is a two-column HTML table, with a ``<tr>`` for each field.
|
|
Notice the following:
|
|
|
|
* For flexibility, the output does *not* include the ``<table>`` and
|
|
``</table>`` tags, nor does it include the ``<form>`` and ``</form>``
|
|
tags or an ``<input type="submit">`` tag. It's your job to do that.
|
|
|
|
* Each field type has a default HTML representation. ``CharField`` and
|
|
``EmailField`` are represented by an ``<input type="text">``.
|
|
``BooleanField`` is represented by an ``<input type="checkbox">``. Note
|
|
these are merely sensible defaults; you can specify which HTML to use for
|
|
a given field by using widgets, which we'll explain shortly.
|
|
|
|
* The HTML ``name`` for each tag is taken directly from its attribute name
|
|
in the ``ContactForm`` class.
|
|
|
|
* The text label for each field -- e.g. ``'Subject:'``, ``'Message:'`` and
|
|
``'Cc myself:'`` is generated from the field name by converting all
|
|
underscores to spaces and upper-casing the first letter. Again, note
|
|
these are merely sensible defaults; you can also specify labels manually.
|
|
|
|
* Each text label is surrounded in an HTML ``<label>`` tag, which points
|
|
to the appropriate form field via its ``id``. Its ``id``, in turn, is
|
|
generated by prepending ``'id_'`` to the field name. The ``id``
|
|
attributes and ``<label>`` tags are included in the output by default, to
|
|
follow best practices, but you can change that behavior.
|
|
|
|
Although ``<table>`` output is the default output style when you ``print`` a
|
|
form, other output styles are available. Each style is available as a method on
|
|
a form object, and each rendering method returns a Unicode object.
|
|
|
|
``as_p()``
|
|
~~~~~~~~~~
|
|
|
|
``Form.as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>``
|
|
containing one field::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_p()
|
|
u'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
|
|
>>> print f.as_p()
|
|
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
|
|
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
|
|
<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>
|
|
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
|
|
|
|
``as_ul()``
|
|
~~~~~~~~~~~
|
|
|
|
``Form.as_ul()`` renders the form as a series of ``<li>`` tags, with each
|
|
``<li>`` containing one field. It does *not* include the ``<ul>`` or ``</ul>``,
|
|
so that you can specify any HTML attributes on the ``<ul>`` for flexibility::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_ul()
|
|
u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
|
|
>>> print f.as_ul()
|
|
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>
|
|
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
|
|
<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>
|
|
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>
|
|
|
|
``as_table()``
|
|
~~~~~~~~~~~~~~
|
|
|
|
Finally, ``Form.as_table()`` outputs the form as an HTML ``<table>``. This is
|
|
exactly the same as ``print``. In fact, when you ``print`` a form object, it
|
|
calls its ``as_table()`` method behind the scenes::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_table()
|
|
u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
|
|
>>> print f.as_table()
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
|
|
|
|
Configuring HTML ``<label>`` tags
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
An HTML ``<label>`` tag designates which label text is associated with which
|
|
form element. This small enhancement makes forms more usable and more accessible
|
|
to assistive devices. It's always a good idea to use ``<label>`` tags.
|
|
|
|
By default, the form rendering methods include HTML ``id`` attributes on the
|
|
form elements and corresponding ``<label>`` tags around the labels. The ``id``
|
|
attribute values are generated by prepending ``id_`` to the form field names.
|
|
This behavior is configurable, though, if you want to change the ``id``
|
|
convention or remove HTML ``id`` attributes and ``<label>`` tags entirely.
|
|
|
|
Use the ``auto_id`` argument to the ``Form`` constructor to control the label
|
|
and ``id`` behavior. This argument must be ``True``, ``False`` or a string.
|
|
|
|
If ``auto_id`` is ``False``, then the form output will not include ``<label>``
|
|
tags nor ``id`` attributes::
|
|
|
|
>>> f = ContactForm(auto_id=False)
|
|
>>> print f.as_table()
|
|
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
|
|
<tr><th>Sender:</th><td><input type="text" name="sender" /></td></tr>
|
|
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
|
|
>>> print f.as_ul()
|
|
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
|
|
<li>Message: <input type="text" name="message" /></li>
|
|
<li>Sender: <input type="text" name="sender" /></li>
|
|
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
|
|
>>> print f.as_p()
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
|
|
<p>Message: <input type="text" name="message" /></p>
|
|
<p>Sender: <input type="text" name="sender" /></p>
|
|
<p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
|
|
|
|
If ``auto_id`` is set to ``True``, then the form output *will* include
|
|
``<label>`` tags and will simply use the field name as its ``id`` for each form
|
|
field::
|
|
|
|
>>> f = ContactForm(auto_id=True)
|
|
>>> print f.as_table()
|
|
<tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
|
|
<tr><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr>
|
|
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
|
|
>>> print f.as_ul()
|
|
<li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
|
|
<li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
|
|
<li><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li>
|
|
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
|
|
>>> print f.as_p()
|
|
<p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
|
|
<p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
|
|
<p><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p>
|
|
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>
|
|
|
|
If ``auto_id`` is set to a string containing the format character ``'%s'``,
|
|
then the form output will include ``<label>`` tags, and will generate ``id``
|
|
attributes based on the format string. For example, for a format string
|
|
``'field_%s'``, a field named ``subject`` will get the ``id`` value
|
|
``'field_subject'``. Continuing our example::
|
|
|
|
>>> f = ContactForm(auto_id='id_for_%s')
|
|
>>> print f.as_table()
|
|
<tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
|
|
<tr><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr>
|
|
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
|
|
>>> print f.as_ul()
|
|
<li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
|
|
<li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
|
|
<li><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li>
|
|
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
|
|
>>> print f.as_p()
|
|
<p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
|
|
<p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
|
|
<p><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p>
|
|
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>
|
|
|
|
If ``auto_id`` is set to any other true value -- such as a string that doesn't
|
|
include ``%s`` -- then the library will act as if ``auto_id`` is ``True``.
|
|
|
|
By default, ``auto_id`` is set to the string ``'id_%s'``.
|
|
|
|
Normally, a colon (``:``) will be appended after any label name when a form is
|
|
rendered. It's possible to change the colon to another character, or omit it
|
|
entirely, using the ``label_suffix`` parameter::
|
|
|
|
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
|
|
>>> print f.as_ul()
|
|
<li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
|
|
<li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li>
|
|
<li><label for="id_for_sender">Sender</label> <input type="text" name="sender" id="id_for_sender" /></li>
|
|
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
|
|
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
|
|
>>> print f.as_ul()
|
|
<li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
|
|
<li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li>
|
|
<li><label for="id_for_sender">Sender -></label> <input type="text" name="sender" id="id_for_sender" /></li>
|
|
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
|
|
|
|
Note that the label suffix is added only if the last character of the
|
|
label isn't a punctuation character (``.``, ``!``, ``?`` or ``:``)
|
|
|
|
Notes on field ordering
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In the ``as_p()``, ``as_ul()`` and ``as_table()`` shortcuts, the fields are
|
|
displayed in the order in which you define them in your form class. For
|
|
example, in the ``ContactForm`` example, the fields are defined in the order
|
|
``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
|
|
output, just change the order in which those fields are listed in the class.
|
|
|
|
How errors are displayed
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you render a bound ``Form`` object, the act of rendering will automatically
|
|
run the form's validation if it hasn't already happened, and the HTML output
|
|
will include the validation errors as a ``<ul class="errorlist">`` near the
|
|
field. The particular positioning of the error messages depends on the output
|
|
method you're using::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid e-mail address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data, auto_id=False)
|
|
>>> print f.as_table()
|
|
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
|
|
<tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
|
|
<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>
|
|
<tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
|
|
>>> print f.as_ul()
|
|
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
|
|
<li>Message: <input type="text" name="message" value="Hi there" /></li>
|
|
<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>
|
|
<li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
|
|
>>> print f.as_p()
|
|
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
|
|
<p>Message: <input type="text" name="message" value="Hi there" /></p>
|
|
<p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p>
|
|
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
|
|
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
|
|
|
|
Customizing the error list format
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
By default, forms use ``django.newforms.util.ErrorList`` to format validation
|
|
errors. If you'd like to use an alternate class for displaying errors, you can
|
|
pass that in at construction time::
|
|
|
|
>>> from django.newforms.util import ErrorList
|
|
>>> class DivErrorList(ErrorList):
|
|
... def __unicode__(self):
|
|
... return self.as_divs()
|
|
... def as_divs(self):
|
|
... if not self: return u''
|
|
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
|
|
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
|
|
>>> f.as_p()
|
|
<div class="errorlist"><div class="error">This field is required.</div></div>
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
|
|
<p>Message: <input type="text" name="message" value="Hi there" /></p>
|
|
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
|
|
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
|
|
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
|
|
|
|
More granular output
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``as_p()``, ``as_ul()`` and ``as_table()`` methods are simply shortcuts for
|
|
lazy developers -- they're not the only way a form object can be displayed.
|
|
|
|
To display the HTML for a single field in your form, use dictionary lookup
|
|
syntax using the field's name as the key, and print the resulting object::
|
|
|
|
>>> f = ContactForm()
|
|
>>> print f['subject']
|
|
<input id="id_subject" type="text" name="subject" maxlength="100" />
|
|
>>> print f['message']
|
|
<input type="text" name="message" id="id_message" />
|
|
>>> print f['sender']
|
|
<input type="text" name="sender" id="id_sender" />
|
|
>>> print f['cc_myself']
|
|
<input type="checkbox" name="cc_myself" id="id_cc_myself" />
|
|
|
|
Call ``str()`` or ``unicode()`` on the field to get its rendered HTML as a
|
|
string or Unicode object, respectively::
|
|
|
|
>>> str(f['subject'])
|
|
'<input id="id_subject" type="text" name="subject" maxlength="100" />'
|
|
>>> unicode(f['subject'])
|
|
u'<input id="id_subject" type="text" name="subject" maxlength="100" />'
|
|
|
|
The field-specific output honors the form object's ``auto_id`` setting::
|
|
|
|
>>> f = ContactForm(auto_id=False)
|
|
>>> print f['message']
|
|
<input type="text" name="message" />
|
|
>>> f = ContactForm(auto_id='id_%s')
|
|
>>> print f['message']
|
|
<input type="text" name="message" id="id_message" />
|
|
|
|
For a field's list of errors, access the field's ``errors`` attribute. This
|
|
is a list-like object that is displayed as an HTML ``<ul class="errorlist">``
|
|
when printed::
|
|
|
|
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
|
|
>>> f = ContactForm(data, auto_id=False)
|
|
>>> print f['message']
|
|
<input type="text" name="message" />
|
|
>>> f['message'].errors
|
|
[u'This field is required.']
|
|
>>> print f['message'].errors
|
|
<ul class="errorlist"><li>This field is required.</li></ul>
|
|
>>> f['subject'].errors
|
|
[]
|
|
>>> print f['subject'].errors
|
|
|
|
>>> str(f['subject'].errors)
|
|
''
|
|
|
|
Using forms in views and templates
|
|
----------------------------------
|
|
|
|
Let's put this all together and use the ``ContactForm`` example in a Django
|
|
view and template.
|
|
|
|
Simple view example
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
This example view displays the contact form by default and validates/processes
|
|
it if accessed via a POST request::
|
|
|
|
def contact(request):
|
|
if request.method == 'POST':
|
|
form = ContactForm(request.POST)
|
|
if form.is_valid():
|
|
# Do form processing here...
|
|
return HttpResponseRedirect('/url/on_success/')
|
|
else:
|
|
form = ContactForm()
|
|
return render_to_response('contact.html', {'form': form})
|
|
|
|
Simple template example
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The template in the above view example, ``contact.html``, is responsible for
|
|
displaying the form as HTML. To do this, we can use the techniques outlined in
|
|
the "Outputting forms as HTML" section above.
|
|
|
|
The simplest way to display a form's HTML is to use the variable on its own,
|
|
like this::
|
|
|
|
<form method="post" action="">
|
|
<table>{{ form }}</table>
|
|
<input type="submit" />
|
|
</form>
|
|
|
|
The above template code will display the form as an HTML table, using the
|
|
``form.as_table()`` method explained previously. This works because Django's
|
|
template system displays an object's ``__str__()`` value, and the ``Form``
|
|
class' ``__str__()`` method calls its ``as_table()`` method.
|
|
|
|
The following is equivalent but a bit more explicit::
|
|
|
|
<form method="post" action="">
|
|
<table>{{ form.as_table }}</table>
|
|
<input type="submit" />
|
|
</form>
|
|
|
|
``form.as_ul`` and ``form.as_p`` are also available, as you may expect.
|
|
|
|
Note that in the above two examples, we included the ``<form>``, ``<table>``
|
|
``<input type="submit" />``, ``</table>`` and ``</form>`` tags. The form
|
|
convenience methods (``as_table()``, ``as_ul()`` and ``as_p()``) do not include
|
|
that HTML.
|
|
|
|
Complex template output
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
As we've stressed several times, the ``as_table()``, ``as_ul()`` and ``as_p()``
|
|
methods are just shortcuts for the common case. You can also work with the
|
|
individual fields for complete template control over the form's design.
|
|
|
|
The easiest way is to iterate over the form's fields, with
|
|
``{% for field in form %}``. For example::
|
|
|
|
<form method="post" action="">
|
|
<dl>
|
|
{% for field in form %}
|
|
<dt>{{ field.label_tag }}</dt>
|
|
<dd>{{ field }}</dd>
|
|
{% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
|
|
{% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}
|
|
{% endfor %}
|
|
</dl>
|
|
<input type="submit" />
|
|
</form>
|
|
|
|
This iteration technique is useful if you want to apply the same HTML
|
|
formatting to each field, or if you don't know the names of the form fields
|
|
ahead of time. Note that the fields will be iterated over in the order in which
|
|
they're defined in the ``Form`` class.
|
|
|
|
Alternatively, you can arrange the form's fields explicitly, by name. Do that
|
|
by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name.
|
|
For example::
|
|
|
|
<form method="post" action="">
|
|
<ul class="myformclass">
|
|
<li>{{ form.sender.label_tag }} {{ form.sender }}</li>
|
|
<li class="helptext">{{ form.sender.help_text }}</li>
|
|
{% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</ul>{% endif %}
|
|
|
|
<li>{{ form.subject.label_tag }} {{ form.subject }}</li>
|
|
<li class="helptext">{{ form.subject.help_text }}</li>
|
|
{% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</ul>{% endif %}
|
|
|
|
...
|
|
</ul>
|
|
</form>
|
|
|
|
Binding uploaded files to a form
|
|
--------------------------------
|
|
|
|
**New in Django development version**
|
|
|
|
Dealing with forms that have ``FileField`` and ``ImageField`` fields
|
|
is a little more complicated than a normal form.
|
|
|
|
Firstly, in order to upload files, you'll need to make sure that your
|
|
``<form>`` element correctly defines the ``enctype`` as
|
|
``"multipart/form-data"``::
|
|
|
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
|
|
|
Secondly, when you use the form, you need to bind the file data. File
|
|
data is handled separately to normal form data, so when your form
|
|
contains a ``FileField`` and ``ImageField``, you will need to specify
|
|
a second argument when you bind your form. So if we extend our
|
|
ContactForm to include an ``ImageField`` called ``mugshot``, we
|
|
need to bind the file data containing the mugshot image::
|
|
|
|
# Bound form with an image field
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> file_data = {'mugshot': {'filename':'face.jpg'
|
|
... 'content': <file data>}}
|
|
>>> f = ContactFormWithMugshot(data, file_data)
|
|
|
|
In practice, you will usually specify ``request.FILES`` as the source
|
|
of file data (just like you use ``request.POST`` as the source of
|
|
form data)::
|
|
|
|
# Bound form with an image field, data from the request
|
|
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
|
|
|
|
Constructing an unbound form is the same as always -- just omit both
|
|
form data *and* file data::
|
|
|
|
# Unbound form with a image field
|
|
>>> f = ContactFormWithMugshot()
|
|
|
|
Testing for multipart forms
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you're writing reusable views or templates, you may not know ahead of time
|
|
whether your form is a multipart form or not. The ``is_multipart()`` method
|
|
tells you whether the form requires multipart encoding for submission::
|
|
|
|
>>> f = ContactFormWithMugshot()
|
|
>>> f.is_multipart()
|
|
True
|
|
|
|
Here's an example of how you might use this in a template::
|
|
|
|
{% if form.is_multipart %}
|
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
|
{% else %}
|
|
<form method="post" action="/foo/">
|
|
{% endif %}
|
|
{% form %}
|
|
</form>
|
|
|
|
Subclassing forms
|
|
-----------------
|
|
|
|
If you have multiple ``Form`` classes that share fields, you can use
|
|
subclassing to remove redundancy.
|
|
|
|
When you subclass a custom ``Form`` class, the resulting subclass will
|
|
include all fields of the parent class(es), followed by the fields you define
|
|
in the subclass.
|
|
|
|
In this example, ``ContactFormWithPriority`` contains all the fields from
|
|
``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
|
|
fields are ordered first::
|
|
|
|
>>> class ContactFormWithPriority(ContactForm):
|
|
... priority = forms.CharField()
|
|
>>> f = ContactFormWithPriority(auto_id=False)
|
|
>>> print f.as_ul()
|
|
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
|
|
<li>Message: <input type="text" name="message" /></li>
|
|
<li>Sender: <input type="text" name="sender" /></li>
|
|
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
|
|
<li>Priority: <input type="text" name="priority" /></li>
|
|
|
|
It's possible to subclass multiple forms, treating forms as "mix-ins." In this
|
|
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
|
|
(in that order), and its field list includes the fields from the parent
|
|
classes::
|
|
|
|
>>> class PersonForm(Form):
|
|
... first_name = CharField()
|
|
... last_name = CharField()
|
|
>>> class InstrumentForm(Form):
|
|
... instrument = CharField()
|
|
>>> class BeatleForm(PersonForm, InstrumentForm):
|
|
... haircut_type = CharField()
|
|
>>> b = BeatleForm(auto_id=False)
|
|
>>> print b.as_ul()
|
|
<li>First name: <input type="text" name="first_name" /></li>
|
|
<li>Last name: <input type="text" name="last_name" /></li>
|
|
<li>Instrument: <input type="text" name="instrument" /></li>
|
|
<li>Haircut type: <input type="text" name="haircut_type" /></li>
|
|
|
|
|
|
Prefixes for forms
|
|
------------------
|
|
|
|
You can put several Django forms inside one ``<form>`` tag. To give each
|
|
``Form`` its own namespace you need to use the ``prefix`` keyword argument::
|
|
|
|
>>> mother = PersonForm(prefix="mother")
|
|
>>> father = PersonForm(prefix="father")
|
|
>>> print mother.as_ul()
|
|
<li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" /></li>
|
|
<li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" /></li>
|
|
>>> print father.as_ul()
|
|
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li>
|
|
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li>
|
|
|
|
|
|
Fields
|
|
======
|
|
|
|
When you create a ``Form`` class, the most important part is defining the
|
|
fields of the form. Each field has custom validation logic, along with a few
|
|
other hooks.
|
|
|
|
Although the primary way you'll use ``Field`` classes is in ``Form`` classes,
|
|
you can also instantiate them and use them directly to get a better idea of
|
|
how they work. Each ``Field`` instance has a ``clean()`` method, which takes
|
|
a single argument and either raises a ``django.newforms.ValidationError``
|
|
exception or returns the clean value::
|
|
|
|
>>> f = forms.EmailField()
|
|
>>> f.clean('foo@example.com')
|
|
u'foo@example.com'
|
|
>>> f.clean(u'foo@example.com')
|
|
u'foo@example.com'
|
|
>>> f.clean('invalid e-mail address')
|
|
Traceback (most recent call last):
|
|
...
|
|
ValidationError: [u'Enter a valid e-mail address.']
|
|
|
|
If you've used Django's old forms/validation framework, take care in noticing
|
|
this ``ValidationError`` is different than the previous ``ValidationError``.
|
|
This one lives at ``django.newforms.ValidationError`` rather than
|
|
``django.core.validators.ValidationError``.
|
|
|
|
Core field arguments
|
|
--------------------
|
|
|
|
Each ``Field`` class constructor takes at least these arguments. Some
|
|
``Field`` classes take additional, field-specific arguments, but the following
|
|
should *always* be accepted:
|
|
|
|
``required``
|
|
~~~~~~~~~~~~
|
|
|
|
By default, each ``Field`` class assumes the value is required, so if you pass
|
|
an empty value -- either ``None`` or the empty string (``""``) -- then
|
|
``clean()`` will raise a ``ValidationError`` exception::
|
|
|
|
>>> f = forms.CharField()
|
|
>>> f.clean('foo')
|
|
u'foo'
|
|
>>> 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(' ')
|
|
u' '
|
|
>>> f.clean(0)
|
|
u'0'
|
|
>>> f.clean(True)
|
|
u'True'
|
|
>>> f.clean(False)
|
|
u'False'
|
|
|
|
To specify that a field is *not* required, pass ``required=False`` to the
|
|
``Field`` constructor::
|
|
|
|
>>> f = forms.CharField(required=False)
|
|
>>> f.clean('foo')
|
|
u'foo'
|
|
>>> f.clean('')
|
|
u''
|
|
>>> f.clean(None)
|
|
u''
|
|
>>> f.clean(0)
|
|
u'0'
|
|
>>> f.clean(True)
|
|
u'True'
|
|
>>> f.clean(False)
|
|
u'False'
|
|
|
|
If a ``Field`` has ``required=False`` and you pass ``clean()`` an empty value,
|
|
then ``clean()`` will return a *normalized* empty value rather than raising
|
|
``ValidationError``. For ``CharField``, this will be a Unicode empty string.
|
|
For other ``Field`` classes, it might be ``None``. (This varies from field to
|
|
field.)
|
|
|
|
``label``
|
|
~~~~~~~~~
|
|
|
|
The ``label`` argument lets you specify the "human-friendly" label for this
|
|
field. This is used when the ``Field`` is displayed in a ``Form``.
|
|
|
|
As explained in "Outputting forms as HTML" above, the default label for a
|
|
``Field`` is generated from the field name by converting all underscores to
|
|
spaces and upper-casing the first letter. Specify ``label`` if that default
|
|
behavior doesn't result in an adequate label.
|
|
|
|
Here's a full example ``Form`` that implements ``label`` for two of its fields.
|
|
We've specified ``auto_id=False`` to simplify the output::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField(label='Your name')
|
|
... url = forms.URLField(label='Your Web site', required=False)
|
|
... comment = forms.CharField()
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> print f
|
|
<tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
|
|
<tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
|
|
``initial``
|
|
~~~~~~~~~~~
|
|
|
|
The ``initial`` argument lets you specify the initial value to use when
|
|
rendering this ``Field`` in an unbound ``Form``.
|
|
|
|
The use-case for this is when you want to display an "empty" form in which a
|
|
field is initialized to a particular value. For example::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField(initial='Your name')
|
|
... url = forms.URLField(initial='http://')
|
|
... comment = forms.CharField()
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> print f
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
|
|
You may be thinking, why not just pass a dictionary of the initial values as
|
|
data when displaying the form? Well, if you do that, you'll trigger validation,
|
|
and the HTML output will include any validation errors::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField()
|
|
... url = forms.URLField()
|
|
... comment = forms.CharField()
|
|
>>> default_data = {'name': 'Your name', 'url': 'http://'}
|
|
>>> f = CommentForm(default_data, auto_id=False)
|
|
>>> print f
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
|
|
<tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr>
|
|
<tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
|
|
|
|
This is why ``initial`` values are only displayed for unbound forms. For bound
|
|
forms, the HTML output will use the bound data.
|
|
|
|
Also note that ``initial`` values are *not* used as "fallback" data in
|
|
validation if a particular field's value is not given. ``initial`` values are
|
|
*only* intended for initial form display::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField(initial='Your name')
|
|
... url = forms.URLField(initial='http://')
|
|
... comment = forms.CharField()
|
|
>>> data = {'name': '', 'url': '', 'comment': 'Foo'}
|
|
>>> f = CommentForm(data)
|
|
>>> f.is_valid()
|
|
False
|
|
# The form does *not* fall back to using the initial values.
|
|
>>> f.errors
|
|
{'url': [u'This field is required.'], 'name': [u'This field is required.']}
|
|
|
|
``widget``
|
|
~~~~~~~~~~
|
|
|
|
The ``widget`` argument lets you specify a ``Widget`` class to use when
|
|
rendering this ``Field``. See `Widgets`_ below for more information.
|
|
|
|
``help_text``
|
|
~~~~~~~~~~~~~
|
|
|
|
The ``help_text`` argument lets you specify descriptive text for this
|
|
``Field``. If you provide ``help_text``, it will be displayed next to the
|
|
``Field`` when the ``Field`` is rendered by one of the convenience ``Form``
|
|
methods (e.g., ``as_ul()``).
|
|
|
|
Here's a full example ``Form`` that implements ``help_text`` for two of its
|
|
fields. We've specified ``auto_id=False`` to simplify the output::
|
|
|
|
>>> class HelpTextContactForm(forms.Form):
|
|
... subject = forms.CharField(max_length=100, help_text='100 characters max.')
|
|
... message = forms.CharField()
|
|
... sender = forms.EmailField(help_text='A valid e-mail address, please.')
|
|
... cc_myself = forms.BooleanField()
|
|
>>> f = HelpTextContactForm(auto_id=False)
|
|
>>> print f.as_table()
|
|
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr>
|
|
<tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
|
|
<tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr>
|
|
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
|
|
>>> print f.as_ul()
|
|
<li>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li>
|
|
<li>Message: <input type="text" name="message" /></li>
|
|
<li>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li>
|
|
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
|
|
>>> print f.as_p()
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p>
|
|
<p>Message: <input type="text" name="message" /></p>
|
|
<p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p>
|
|
<p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
|
|
|
|
Dynamic initial values
|
|
----------------------
|
|
|
|
The ``initial`` argument to ``Field`` (explained above) lets you hard-code the
|
|
initial value for a ``Field`` -- but what if you want to declare the initial
|
|
value at runtime? For example, you might want to fill in a ``username`` field
|
|
with the username of the current session.
|
|
|
|
To accomplish this, use the ``initial`` argument to a ``Form``. This argument,
|
|
if given, should be a dictionary mapping field names to initial values. Only
|
|
include the fields for which you're specifying an initial value; it's not
|
|
necessary to include every field in your form. For example::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField()
|
|
... url = forms.URLField()
|
|
... comment = forms.CharField()
|
|
>>> f = CommentForm(initial={'name': 'your username'}, auto_id=False)
|
|
>>> print f
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
>>> f = CommentForm(initial={'name': 'another username'}, auto_id=False)
|
|
>>> print f
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
|
|
Just like the ``initial`` parameter to ``Field``, these values are only
|
|
displayed for unbound forms, and they're not used as fallback values if a
|
|
particular value isn't provided.
|
|
|
|
Finally, note that if a ``Field`` defines ``initial`` *and* you include
|
|
``initial`` when instantiating the ``Form``, then the latter ``initial`` will
|
|
have precedence. In this example, ``initial`` is provided both at the field
|
|
level and at the form instance level, and the latter gets precedence::
|
|
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField(initial='class')
|
|
... url = forms.URLField()
|
|
... comment = forms.CharField()
|
|
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
|
|
>>> print f
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
|
|
Built-in ``Field`` classes
|
|
--------------------------
|
|
|
|
Naturally, the ``newforms`` library comes with a set of ``Field`` classes that
|
|
represent common validation needs. This section documents each built-in field.
|
|
|
|
For each field, we describe the default widget used if you don't specify
|
|
``widget``. We also specify the value returned when you provide an empty value
|
|
(see the section on ``required`` above to understand what that means).
|
|
|
|
``BooleanField``
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``CheckboxInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``True`` or ``False`` value.
|
|
* Validates nothing (i.e., it never raises a ``ValidationError``).
|
|
|
|
``CharField``
|
|
~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates nothing, unless ``max_length`` or ``min_length`` is provided.
|
|
|
|
Has two optional arguments for validation, ``max_length`` and ``min_length``.
|
|
If provided, these arguments ensure that the string is at most or at least the
|
|
given length.
|
|
|
|
``ChoiceField``
|
|
~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``Select``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates that the given value exists in the list of choices.
|
|
|
|
Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
|
|
tuple) of 2-tuples to use as choices for this field.
|
|
|
|
``DateField``
|
|
~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``datetime.date`` object.
|
|
* Validates that the given value is either a ``datetime.date``,
|
|
``datetime.datetime`` or string formatted in a particular date format.
|
|
|
|
Takes one optional argument, ``input_formats``, which is a list of formats used
|
|
to attempt to convert a string to a valid ``datetime.date`` object.
|
|
|
|
If no ``input_formats`` argument is provided, the default input formats are::
|
|
|
|
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
|
|
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
|
|
'%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
|
|
'%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
|
|
'%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
|
|
|
|
``DateTimeField``
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``datetime.datetime`` object.
|
|
* Validates that the given value is either a ``datetime.datetime``,
|
|
``datetime.date`` or string formatted in a particular datetime format.
|
|
|
|
Takes one optional argument, ``input_formats``, which is a list of formats used
|
|
to attempt to convert a string to a valid ``datetime.datetime`` object.
|
|
|
|
If no ``input_formats`` argument is provided, the default input formats are::
|
|
|
|
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
|
|
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
|
|
'%Y-%m-%d', # '2006-10-25'
|
|
'%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
|
|
'%m/%d/%Y %H:%M', # '10/25/2006 14:30'
|
|
'%m/%d/%Y', # '10/25/2006'
|
|
'%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
|
|
'%m/%d/%y %H:%M', # '10/25/06 14:30'
|
|
'%m/%d/%y', # '10/25/06'
|
|
|
|
``DecimalField``
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
**New in Django development version**
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``decimal``.
|
|
* Validates that the given value is a decimal. Leading and trailing
|
|
whitespace is ignored.
|
|
|
|
Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``,
|
|
and ``decimal_places``. The first two define the limits for the fields value.
|
|
``max_digits`` is the maximum number of digits (those before the decimal
|
|
point plus those after the decimal point, with leading zeros stripped)
|
|
permitted in the value, whilst ``decimal_places`` is the maximum number of
|
|
decimal places permitted.
|
|
|
|
``EmailField``
|
|
~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates that the given value is a valid e-mail address, using a
|
|
moderately complex regular expression.
|
|
|
|
Has two optional arguments for validation, ``max_length`` and ``min_length``.
|
|
If provided, these arguments ensure that the string is at most or at least the
|
|
given length.
|
|
|
|
``FileField``
|
|
~~~~~~~~~~~~~
|
|
|
|
**New in Django development version**
|
|
|
|
* Default widget: ``FileInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: An ``UploadedFile`` object that wraps the file content
|
|
and file name into a single object.
|
|
* Validates that non-empty file data has been bound to the form.
|
|
|
|
An ``UploadedFile`` object has two attributes:
|
|
|
|
====================== =====================================================
|
|
Argument Description
|
|
====================== =====================================================
|
|
``filename`` The name of the file, provided by the uploading
|
|
client.
|
|
``content`` The array of bytes comprising the file content.
|
|
====================== =====================================================
|
|
|
|
The string representation of an ``UploadedFile`` is the same as the filename
|
|
attribute.
|
|
|
|
When you use a ``FileField`` on a form, you must also remember to
|
|
`bind the file data to the form`_.
|
|
|
|
.. _`bind the file data to the form`: `Binding uploaded files to a form`_
|
|
|
|
``ImageField``
|
|
~~~~~~~~~~~~~~
|
|
|
|
**New in Django development version**
|
|
|
|
* Default widget: ``FileInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: An ``UploadedFile`` object that wraps the file content
|
|
and file name into a single object.
|
|
* Validates that file data has been bound to the form, and that the
|
|
file is of an image format understood by PIL.
|
|
|
|
Using an ImageField requires that the `Python Imaging Library`_ is installed.
|
|
|
|
When you use a ``FileField`` on a form, you must also remember to
|
|
`bind the file data to the form`_.
|
|
|
|
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
|
|
|
|
``IntegerField``
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python integer or long integer.
|
|
* Validates that the given value is an integer. Leading and trailing
|
|
whitespace is allowed, as in Python's ``int()`` function.
|
|
|
|
Takes two optional arguments for validation, ``max_value`` and ``min_value``.
|
|
These control the range of values permitted in the field.
|
|
|
|
``IPAddressField``
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates that the given value is a valid IPv4 address, using a regular
|
|
expression.
|
|
|
|
``MultipleChoiceField``
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``SelectMultiple``
|
|
* Empty value: ``[]`` (an empty list)
|
|
* Normalizes to: A list of Unicode objects.
|
|
* Validates that every value in the given list of values exists in the list
|
|
of choices.
|
|
|
|
Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
|
|
tuple) of 2-tuples to use as choices for this field.
|
|
|
|
``NullBooleanField``
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``NullBooleanSelect``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``True``, ``False`` or ``None`` value.
|
|
* Validates nothing (i.e., it never raises a ``ValidationError``).
|
|
|
|
``RegexField``
|
|
~~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates that the given value matches against a certain regular
|
|
expression.
|
|
|
|
Takes one required argument, ``regex``, which is a regular expression specified
|
|
either as a string or a compiled regular expression object.
|
|
|
|
Also takes the following optional arguments:
|
|
|
|
====================== =====================================================
|
|
Argument Description
|
|
====================== =====================================================
|
|
``max_length`` Ensures the string has at most this many characters.
|
|
``min_length`` Ensures the string has at least this many characters.
|
|
``error_message`` Error message to return for failed validation. If no
|
|
message is provided, a generic error message will be
|
|
used.
|
|
====================== =====================================================
|
|
|
|
``TimeField``
|
|
~~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``None``
|
|
* Normalizes to: A Python ``datetime.time`` object.
|
|
* Validates that the given value is either a ``datetime.time`` or string
|
|
formatted in a particular time format.
|
|
|
|
Takes one optional argument, ``input_formats``, which is a list of formats used
|
|
to attempt to convert a string to a valid ``datetime.time`` object.
|
|
|
|
If no ``input_formats`` argument is provided, the default input formats are::
|
|
|
|
'%H:%M:%S', # '14:30:59'
|
|
'%H:%M', # '14:30'
|
|
|
|
``URLField``
|
|
~~~~~~~~~~~~
|
|
|
|
* Default widget: ``TextInput``
|
|
* Empty value: ``''`` (an empty string)
|
|
* Normalizes to: A Unicode object.
|
|
* Validates that the given value is a valid URL.
|
|
|
|
Takes the following optional arguments:
|
|
|
|
======================== =====================================================
|
|
Argument Description
|
|
======================== =====================================================
|
|
``max_length`` Ensures the string has at most this many characters.
|
|
``min_length`` Ensures the string has at least this many characters.
|
|
``verify_exists`` If ``True``, the validator will attempt to load the
|
|
given URL, raising ``ValidationError`` if the page
|
|
gives a 404. Defaults to ``False``.
|
|
``validator_user_agent`` String used as the user-agent used when checking for
|
|
a URL's existence. Defaults to the value of the
|
|
``URL_VALIDATOR_USER_AGENT`` setting.
|
|
======================== =====================================================
|
|
|
|
Slightly complex built-in ``Field`` classes
|
|
-------------------------------------------
|
|
|
|
The following are not yet documented here. See the unit tests, linked-to from
|
|
the bottom of this document, for examples of their use.
|
|
|
|
``ComboField``
|
|
~~~~~~~~~~~~~~
|
|
|
|
``MultiValueField``
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
``SplitDateTimeField``
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Creating custom fields
|
|
----------------------
|
|
|
|
If the built-in ``Field`` classes don't meet your needs, you can easily create
|
|
custom ``Field`` classes. To do this, just create a subclass of
|
|
``django.newforms.Field``. Its only requirements are that it implement a
|
|
``clean()`` method and that its ``__init__()`` method accept the core arguments
|
|
mentioned above (``required``, ``label``, ``initial``, ``widget``,
|
|
``help_text``).
|
|
|
|
Custom form and field validation
|
|
---------------------------------
|
|
|
|
Form validation happens when the data is cleaned. If you want to customise
|
|
this process, there are various places you can change, each one serving a
|
|
different purpose. Three types of cleaning methods are run during form
|
|
processing. These are normally executed when you call the ``is_valid()``
|
|
method on a form. There are other things that can trigger cleaning and
|
|
validation (accessing the ``errors`` attribute or calling ``full_clean()``
|
|
directly), but normally they won't be needed.
|
|
|
|
In general, any cleaning method can raise ``ValidationError`` if there is a
|
|
problem with the data it is processing, passing the relevant error message to
|
|
the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the
|
|
method should return the cleaned (normalised) data as a Python object.
|
|
|
|
If you detect multiple errors during a cleaning method and wish to signal all
|
|
of them to the form submitter, it is possible to pass a list of errors to the
|
|
``ValidationError`` constructor.
|
|
|
|
The three types of cleaning methods are:
|
|
|
|
* The ``clean()`` method on a Field subclass. This is responsible
|
|
for cleaning the data in a way that is generic for that type of field.
|
|
For example, a FloatField will turn the data into a Python ``float`` or
|
|
raise a ``ValidationError``.
|
|
|
|
* The ``clean_<fieldname>()`` method in a form subclass -- where
|
|
``<fieldname>`` is replaced with the name of the form field attribute.
|
|
This method does any cleaning that is specific to that particular
|
|
attribute, unrelated to the type of field that it is. This method is not
|
|
passed any parameters. You will need to look up the value of the field
|
|
in ``self.cleaned_data`` and remember that it will be a Python object
|
|
at this point, not the original string submitted in the form (it will be
|
|
in ``cleaned_data`` because the general field ``clean()`` method, above,
|
|
has already cleaned the data once).
|
|
|
|
For example, if you wanted to validate that the contents of a
|
|
``CharField`` called ``serialnumber`` was unique,
|
|
``clean_serialnumber()`` would be the right place to do this. You don't
|
|
need a specific field (it's just a ``CharField``), but you want a
|
|
formfield-specific piece of validation and, possibly,
|
|
cleaning/normalizing the data.
|
|
|
|
* The Form subclass's ``clean()`` method. This method can perform
|
|
any validation that requires access to multiple fields from the form at
|
|
once. This is where you might put in things to check that if field ``A``
|
|
is supplied, field ``B`` must contain a valid email address and the
|
|
like. The data that this method returns is the final ``cleaned_data``
|
|
attribute for the form, so don't forget to return the full list of
|
|
cleaned data if you override this method (by default, ``Form.clean()``
|
|
just returns ``self.cleaned_data``).
|
|
|
|
Note that any errors raised by your ``Form.clean()`` override will not
|
|
be associated with any field in particular. They go into a special
|
|
"field" (called ``__all__``, which you can access via the
|
|
``non_field_errors()`` method if you need to.
|
|
|
|
These methods are run in the order given above, one field at a time. That is,
|
|
for each field in the form (in the order they are declared in the form
|
|
definition), the ``Field.clean()`` method (or it's override) is run, then
|
|
``clean_<fieldname>()``. Finally, once those two methods are run for every
|
|
field, the ``Form.clean()`` method, or it's override, is executed.
|
|
|
|
As mentioned above, any of these methods can raise a ``ValidationError``. For
|
|
any field, if the ``Field.clean()`` method raises a ``ValidationError``, any
|
|
field-specific cleaning method is not called. However, the cleaning methods
|
|
for all remaining fields are still executed.
|
|
|
|
The ``clean()`` method for the ``Form`` class or subclass is always run. If
|
|
that method raises a ``ValidationError``, ``cleaned_data`` will be an empty
|
|
dictionary.
|
|
|
|
The previous paragraph means that if you are overriding ``Form.clean()``, you
|
|
should iterate through ``self.cleaned_data.items()``, possibly considering the
|
|
``_errors`` dictionary attribute on the form as well. In this way, you will
|
|
already know which fields have passed their individual validation requirements.
|
|
|
|
A simple example
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
Here's a simple example of a custom field that validates its input is a string
|
|
containing comma-separated e-mail addresses, with at least one address. We'll
|
|
keep it simple and assume e-mail validation is contained in a function called
|
|
``is_valid_email()``. The full class::
|
|
|
|
from django import newforms as forms
|
|
|
|
class MultiEmailField(forms.Field):
|
|
def clean(self, value):
|
|
if not value:
|
|
raise forms.ValidationError('Enter at least one e-mail address.')
|
|
emails = value.split(',')
|
|
for email in emails:
|
|
if not is_valid_email(email):
|
|
raise forms.ValidationError('%s is not a valid e-mail address.' % email)
|
|
return emails
|
|
|
|
Let's alter the ongoing ``ContactForm`` example to demonstrate how you'd use
|
|
this in a form. Simply use ``MultiEmailField`` instead of ``forms.EmailField``,
|
|
like so::
|
|
|
|
class ContactForm(forms.Form):
|
|
subject = forms.CharField(max_length=100)
|
|
message = forms.CharField()
|
|
senders = MultiEmailField()
|
|
cc_myself = forms.BooleanField()
|
|
|
|
Widgets
|
|
=======
|
|
|
|
A widget is Django's representation of a HTML input element. The widget
|
|
handles the rendering of the HTML, and the extraction of data from a GET/POST
|
|
dictionary that corresponds to the widget.
|
|
|
|
Django provides a representation of all the basic HTML widgets, plus some
|
|
commonly used groups of widgets:
|
|
|
|
============================ ===========================================
|
|
Widget HTML Equivalent
|
|
============================ ===========================================
|
|
``TextInput`` ``<input type='text' ...``
|
|
``PasswordInput`` ``<input type='password' ...``
|
|
``HiddenInput`` ``<input type='hidden' ...``
|
|
``MultipleHiddenInput`` Multiple ``<input type='hidden' ...``
|
|
instances.
|
|
``FileInput`` ``<input type='file' ...``
|
|
``Textarea`` ``<textarea>...</textarea>``
|
|
``CheckboxInput`` ``<input type='checkbox' ...``
|
|
``Select`` ``<select><option ...``
|
|
``NullBooleanSelect`` Select widget with options 'Unknown',
|
|
'Yes' and 'No'
|
|
``SelectMultiple`` ``<select multiple='multiple'><option ...``
|
|
``RadioSelect`` ``<ul><li><input type='radio' ...``
|
|
``CheckboxSelectMultiple`` ``<ul><li><input type='checkbox' ...``
|
|
``MultiWidget`` Wrapper around multiple other widgets
|
|
``SplitDateTimeWidget`` Wrapper around two ``TextInput`` widgets:
|
|
one for the Date, and one for the Time.
|
|
============================ ===========================================
|
|
|
|
Specifying widgets
|
|
------------------
|
|
|
|
Whenever you specify a field on a form, Django will use a default widget
|
|
that is appropriate to the type of data that is to be displayed. To find
|
|
which widget is used on which field, see the documentation for the
|
|
built-in Field classes.
|
|
|
|
However, if you want to use a different widget for a field, you can -
|
|
just use the 'widget' argument on the field definition. For example::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField(widget=forms.Textarea)
|
|
|
|
This would specify a form with a comment that uses a larger Textarea widget,
|
|
rather than the default TextInput widget.
|
|
|
|
Customizing widget instances
|
|
----------------------------
|
|
|
|
When Django renders a widget as HTML, it only renders the bare minimum
|
|
HTML - Django doesn't add a class definition, or any other widget-specific
|
|
attributes. This means that all 'TextInput' widgets will appear the same
|
|
on your web page.
|
|
|
|
If you want to make one widget look different to another, you need to
|
|
specify additional attributes for each widget. When you specify a
|
|
widget, you can provide a list of attributes that will be added to the
|
|
rendered HTML for the widget.
|
|
|
|
For example, take the following simple form::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField()
|
|
|
|
This form will include three default TextInput widgets, with default rendering -
|
|
no CSS class, no extra attributes. This means that the inputs boxes provided for
|
|
each widget will be rendered exactly the same::
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> f.as_table()
|
|
<tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url"/></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
|
|
|
On a real web page, you probably don't want every widget to look the same. You
|
|
might want a larger input element for the comment, and you might want the
|
|
'name' widget to have some special CSS class. To do this, you specify a
|
|
custom widget for your fields, and specify some attributes to use
|
|
when rendering those widgets::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField(
|
|
widget=forms.TextInput(attrs={'class':'special'}))
|
|
url = forms.URLField()
|
|
comment = forms.CharField(
|
|
widget=forms.TextInput(attrs={'size':'40'}))
|
|
|
|
Django will then include the extra attributes in the rendered output::
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> f.as_table()
|
|
<tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr>
|
|
<tr><th>Url:</th><td><input type="text" name="url"/></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>
|
|
|
|
Custom Widgets
|
|
--------------
|
|
|
|
When you start to write a lot of forms, you will probably find that you will
|
|
reuse certain sets of widget attributes over and over again. Rather than
|
|
repeat these attribute definitions every time you need them, Django allows
|
|
you to capture those definitions as a custom widget.
|
|
|
|
For example, if you find that you are including a lot of comment fields on forms,
|
|
you could capture the idea of a ``TextInput`` with a specific ``size`` attribute
|
|
as a custom extension to the ``TextInput`` widget::
|
|
|
|
class CommentWidget(forms.TextInput):
|
|
def __init__(self, *args, **kwargs):
|
|
kwargs.setdefault('attrs',{}).update({'size': '40'})
|
|
super(CommentWidget, self).__init__(*args, **kwargs)
|
|
|
|
Then you can use this widget in your forms::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField(widget=CommentWidget)
|
|
|
|
You can even customize your custom widget, in the same way as you would
|
|
any other widget. Adding a once-off class to your ``CommentWidget`` is as
|
|
simple as adding an attribute definition::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField(max_length=20)
|
|
url = forms.URLField()
|
|
comment = forms.CharField(
|
|
widget=CommentWidget(attrs={'class': 'special'}))
|
|
|
|
Django also makes it easy to specify a custom field type that uses your custom
|
|
widget. For example, you could define a customized field type for comments
|
|
by defining::
|
|
|
|
class CommentInput(forms.CharField):
|
|
widget = CommentWidget
|
|
|
|
You can then use this field whenever you have a form that requires a comment::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = CommentInput()
|
|
|
|
Generating forms for models
|
|
===========================
|
|
|
|
If you're building a database-driven app, chances are you'll have forms that
|
|
map closely to Django models. For instance, you might have a ``BlogComment``
|
|
model, and you want to create a form that lets people submit comments. In this
|
|
case, it would be redundant to define the field types in your form, because
|
|
you've already defined the fields in your model.
|
|
|
|
For this reason, Django provides a few helper functions that let you create a
|
|
``Form`` class from a Django model.
|
|
|
|
``form_for_model()``
|
|
--------------------
|
|
|
|
The method ``django.newforms.form_for_model()`` creates a form based on the
|
|
definition of a specific model. Pass it the model class, and it will return a
|
|
``Form`` class that contains a form field for each model field.
|
|
|
|
For example::
|
|
|
|
>>> from django.newforms import form_for_model
|
|
|
|
# Create the form class.
|
|
>>> ArticleForm = form_for_model(Article)
|
|
|
|
# Create an empty form instance.
|
|
>>> f = ArticleForm()
|
|
|
|
It bears repeating that ``form_for_model()`` takes the model *class*, not a
|
|
model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
|
|
|
|
Field types
|
|
~~~~~~~~~~~
|
|
|
|
The generated ``Form`` class will have a form field for every model field. Each
|
|
model field has a corresponding default form field. For example, a
|
|
``CharField`` on a model is represented as a ``CharField`` on a form. A
|
|
model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
|
|
the full list of conversions:
|
|
|
|
=============================== ========================================
|
|
Model field Form field
|
|
=============================== ========================================
|
|
``AutoField`` Not represented in the form
|
|
``BooleanField`` ``BooleanField``
|
|
``CharField`` ``CharField`` with ``max_length`` set to
|
|
the model field's ``max_length``
|
|
``CommaSeparatedIntegerField`` ``CharField``
|
|
``DateField`` ``DateField``
|
|
``DateTimeField`` ``DateTimeField``
|
|
``DecimalField`` ``DecimalField``
|
|
``EmailField`` ``EmailField``
|
|
``FileField`` ``FileField``
|
|
``FilePathField`` ``CharField``
|
|
``FloatField`` ``FloatField``
|
|
``ForeignKey`` ``ModelChoiceField`` (see below)
|
|
``ImageField`` ``ImageField``
|
|
``IntegerField`` ``IntegerField``
|
|
``IPAddressField`` ``IPAddressField``
|
|
``ManyToManyField`` ``ModelMultipleChoiceField`` (see
|
|
below)
|
|
``NullBooleanField`` ``CharField``
|
|
``PhoneNumberField`` ``USPhoneNumberField``
|
|
(from ``django.contrib.localflavor.us``)
|
|
``PositiveIntegerField`` ``IntegerField``
|
|
``PositiveSmallIntegerField`` ``IntegerField``
|
|
``SlugField`` ``CharField``
|
|
``SmallIntegerField`` ``IntegerField``
|
|
``TextField`` ``CharField`` with ``widget=Textarea``
|
|
``TimeField`` ``TimeField``
|
|
``URLField`` ``URLField`` with ``verify_exists`` set
|
|
to the model field's ``verify_exists``
|
|
``USStateField`` ``CharField`` with
|
|
``widget=USStateSelect``
|
|
(``USStateSelect`` is from
|
|
``django.contrib.localflavor.us``)
|
|
``XMLField`` ``CharField`` with ``widget=Textarea``
|
|
=============================== ========================================
|
|
|
|
|
|
.. note::
|
|
The ``FloatField`` form field and ``DecimalField`` model and form fields
|
|
are new in the development version.
|
|
|
|
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
|
|
types are special cases:
|
|
|
|
* ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
|
|
which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
|
|
|
|
* ``ManyToManyField`` is represented by
|
|
``django.newforms.ModelMultipleChoiceField``, which is a
|
|
``MultipleChoiceField`` whose choices are a model ``QuerySet``.
|
|
|
|
In addition, each generated form field has attributes set as follows:
|
|
|
|
* If the model field has ``blank=True``, then ``required`` is set to
|
|
``False`` on the form field. Otherwise, ``required=True``.
|
|
|
|
* The form field's ``label`` is set to the ``verbose_name`` of the model
|
|
field, with the first character capitalized.
|
|
|
|
* The form field's ``help_text`` is set to the ``help_text`` of the model
|
|
field.
|
|
|
|
* If the model field has ``choices`` set, then the form field's ``widget``
|
|
will be set to ``Select``, with choices coming from the model field's
|
|
``choices``.
|
|
|
|
Finally, note that you can override the form field used for a given model
|
|
field. See "Overriding the default field types" below.
|
|
|
|
A full example
|
|
~~~~~~~~~~~~~~
|
|
|
|
Consider this set of models::
|
|
|
|
from django.db import models
|
|
|
|
TITLE_CHOICES = (
|
|
('MR', 'Mr.'),
|
|
('MRS', 'Mrs.'),
|
|
('MS', 'Ms.'),
|
|
)
|
|
|
|
class Author(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
|
|
birth_date = models.DateField(blank=True, null=True)
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
class Book(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
authors = models.ManyToManyField(Author)
|
|
|
|
With these models, a call to ``form_for_model(Author)`` would return a ``Form``
|
|
class equivalent to this::
|
|
|
|
class AuthorForm(forms.Form):
|
|
name = forms.CharField(max_length=100)
|
|
title = forms.CharField(max_length=3,
|
|
widget=forms.Select(choices=TITLE_CHOICES))
|
|
birth_date = forms.DateField(required=False)
|
|
|
|
A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
|
|
this::
|
|
|
|
class BookForm(forms.Form):
|
|
name = forms.CharField(max_length=100)
|
|
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
|
|
|
|
The ``save()`` method
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Every form produced by ``form_for_model()`` also has a ``save()`` method. This
|
|
method creates and saves a database object from the data bound to the form. For
|
|
example::
|
|
|
|
# Create a form instance from POST data.
|
|
>>> f = ArticleForm(request.POST)
|
|
|
|
# Save a new Article object from the form's data.
|
|
>>> new_article = f.save()
|
|
|
|
Note that ``save()`` will raise a ``ValueError`` if the data in the form
|
|
doesn't validate -- i.e., ``if form.errors``.
|
|
|
|
This ``save()`` method accepts an optional ``commit`` keyword argument, which
|
|
accepts either ``True`` or ``False``. If you call ``save()`` with
|
|
``commit=False``, then it will return an object that hasn't yet been saved to
|
|
the database. In this case, it's up to you to call ``save()`` on the resulting
|
|
model instance. This is useful if you want to do custom processing on the
|
|
object before saving it. ``commit`` is ``True`` by default.
|
|
|
|
Another side effect of using ``commit=False`` is seen when your model has
|
|
a many-to-many relation with another model. If your model has a many-to-many
|
|
relation and you specify ``commit=False`` when you save a form, Django cannot
|
|
immediately save the form data for the many-to-many relation. This is because
|
|
it isn't possible to save many-to-many data for an instance until the instance
|
|
exists in the database.
|
|
|
|
To work around this problem, every time you save a form using ``commit=False``,
|
|
Django adds a ``save_m2m()`` method to the form created by ``form_for_model``.
|
|
After you've manually saved the instance produced by the form, you can invoke
|
|
``save_m2m()`` to save the many-to-many form data. For example::
|
|
|
|
# Create a form instance with POST data.
|
|
>>> f = AuthorForm(request.POST)
|
|
|
|
# Create, but don't save the new author instance.
|
|
>>> new_author = f.save(commit=False)
|
|
|
|
# Modify the author in some way.
|
|
>>> new_author.some_field = 'some_value'
|
|
|
|
# Save the new instance.
|
|
>>> new_author.save()
|
|
|
|
# Now, save the many-to-many data for the form.
|
|
>>> f.save_m2m()
|
|
|
|
Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
|
|
When you use a simple ``save()`` on a form, all data -- including
|
|
many-to-many data -- is saved without the need for any additional method calls.
|
|
For example::
|
|
|
|
# Create a form instance with POST data.
|
|
>>> f = AuthorForm(request.POST)
|
|
|
|
# Create and save the new author instance. There's no need to do anything else.
|
|
>>> new_author = f.save()
|
|
|
|
Using an alternate base class
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you want to add custom methods to the form generated by
|
|
``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
|
|
and contains your custom methods. Then, use the ``form`` argument to
|
|
``form_for_model()`` to tell it to use your custom form as its base class.
|
|
For example::
|
|
|
|
# Create the new base class.
|
|
>>> class MyBase(BaseForm):
|
|
... def my_method(self):
|
|
... # Do whatever the method does
|
|
|
|
# Create the form class with a different base class.
|
|
>>> ArticleForm = form_for_model(Article, form=MyBase)
|
|
|
|
# Instantiate the form.
|
|
>>> f = ArticleForm()
|
|
|
|
# Use the base class method.
|
|
>>> f.my_method()
|
|
|
|
Using a subset of fields on the form
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**New in Django development version**
|
|
|
|
In some cases, you may not want all the model fields to appear on the generated
|
|
form. There are two ways of telling ``form_for_model()`` to use only a subset
|
|
of the model fields:
|
|
|
|
1. Set ``editable=False`` on the model field. As a result, *any* form
|
|
created from the model via ``form_for_model()`` will not include that
|
|
field.
|
|
|
|
2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
|
|
given, should be a list of field names to include in the form.
|
|
|
|
For example, if you want a form for the ``Author`` model (defined above)
|
|
that includes only the ``name`` and ``title`` fields, you would specify
|
|
``fields`` like this::
|
|
|
|
PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
|
|
|
|
.. note::
|
|
|
|
If you specify ``fields`` when creating a form with ``form_for_model()``,
|
|
then the fields that are *not* specified will not be set by the form's
|
|
``save()`` method. Django will prevent any attempt to save an incomplete
|
|
model, so if the model does not allow the missing fields to be empty, and
|
|
does not provide a default value for the missing fields, any attempt to
|
|
``save()`` a ``form_for_model`` with missing fields will fail. To avoid
|
|
this failure, you must use ``save(commit=False)`` and manually set any
|
|
extra required fields::
|
|
|
|
instance = form.save(commit=False)
|
|
instance.required_field = 'new value'
|
|
instance.save()
|
|
|
|
See the `section on saving forms`_ for more details on using
|
|
``save(commit=False)``.
|
|
|
|
.. _section on saving forms: `The save() method`_
|
|
|
|
Overriding the default field types
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The default field types, as described in the "Field types" table above, are
|
|
sensible defaults; if you have a ``DateField`` in your model, chances are you'd
|
|
want that to be represented as a ``DateField`` in your form. But
|
|
``form_for_model()`` gives you the flexibility of changing the form field type
|
|
for a given model field. You do this by specifying a **formfield callback**.
|
|
|
|
A formfield callback is a function that, when provided with a model field,
|
|
returns a form field instance. When constructing a form, ``form_for_model()``
|
|
asks the formfield callback to provide form field types.
|
|
|
|
By default, ``form_for_model()`` calls the ``formfield()`` method on the model
|
|
field::
|
|
|
|
def default_callback(field, **kwargs):
|
|
return field.formfield(**kwargs)
|
|
|
|
The ``kwargs`` are any keyword arguments that might be passed to the form
|
|
field, such as ``required=True`` or ``label='Foo'``.
|
|
|
|
For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
|
|
field on the model, you could define the callback::
|
|
|
|
>>> def my_callback(field, **kwargs):
|
|
... if isinstance(field, models.DateField):
|
|
... return MyDateFormField(**kwargs)
|
|
... else:
|
|
... return field.formfield(**kwargs)
|
|
|
|
>>> ArticleForm = form_for_model(Article, formfield_callback=my_callback)
|
|
|
|
Note that your callback needs to handle *all* possible model field types, not
|
|
just the ones that you want to behave differently to the default. That's why
|
|
this example has an ``else`` clause that implements the default behavior.
|
|
|
|
.. warning::
|
|
The field that is passed into the ``formfield_callback`` function in
|
|
``form_for_model()`` and ``form_for_instance`` is the field instance from
|
|
your model's class. You **must not** alter that object at all; treat it
|
|
as read-only!
|
|
|
|
If you make any alterations to that object, it will affect any future
|
|
users of the model class, because you will have changed the field object
|
|
used to construct the class. This is almost certainly what you don't want
|
|
to have happen.
|
|
|
|
Finding the model associated with a form
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The model class that was used to construct the form is available
|
|
using the ``_model`` property of the generated form::
|
|
|
|
>>> ArticleForm = form_for_model(Article)
|
|
>>> ArticleForm._model
|
|
<class 'myapp.models.Article'>
|
|
|
|
``form_for_instance()``
|
|
-----------------------
|
|
|
|
``form_for_instance()`` is like ``form_for_model()``, but it takes a model
|
|
instance instead of a model class::
|
|
|
|
# Create an Author.
|
|
>>> a = Author(name='Joe Smith', title='MR', birth_date=None)
|
|
>>> a.save()
|
|
|
|
# Create a form for this particular Author.
|
|
>>> AuthorForm = form_for_instance(a)
|
|
|
|
# Instantiate the form.
|
|
>>> f = AuthorForm()
|
|
|
|
When a form created by ``form_for_instance()`` is created, the initial
|
|
data values for the form fields are drawn from the instance. However,
|
|
this data is not bound to the form. You will need to bind data to the
|
|
form before the form can be saved.
|
|
|
|
When you call ``save()`` on a form created by ``form_for_instance()``,
|
|
the database instance will be updated. As in ``form_for_model()``, ``save()``
|
|
will raise ``ValueError`` if the data doesn't validate.
|
|
|
|
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
|
|
arguments that behave the same way as they do for ``form_for_model()``.
|
|
|
|
Let's modify the earlier `contact form`_ view example a little bit. Suppose we
|
|
have a ``Message`` model that holds each contact submission. Something like::
|
|
|
|
class Message(models.Model):
|
|
subject = models.CharField(max_length=100)
|
|
message = models.TextField()
|
|
sender = models.EmailField()
|
|
cc_myself = models.BooleanField()
|
|
|
|
You could use this model to create a form (using ``form_for_model()``). You
|
|
could also use existing ``Message`` instances to create a form for editing
|
|
messages. The earlier_ view can be changed slightly to accept the ``id`` value
|
|
of an existing ``Message`` and present it for editing::
|
|
|
|
def contact_edit(request, msg_id):
|
|
# Create the form from the message id.
|
|
message = get_object_or_404(Message, id=msg_id)
|
|
ContactForm = form_for_instance(message)
|
|
|
|
if request.method == 'POST':
|
|
form = ContactForm(request.POST)
|
|
if form.is_valid():
|
|
form.save()
|
|
return HttpResponseRedirect('/url/on_success/')
|
|
else:
|
|
form = ContactForm()
|
|
return render_to_response('contact.html', {'form': form})
|
|
|
|
Aside from how we create the ``ContactForm`` class here, the main point to
|
|
note is that the form display in the ``GET`` branch of the function
|
|
will use the values from the ``message`` instance as initial values for the
|
|
form field.
|
|
|
|
.. _contact form: `Simple view example`_
|
|
.. _earlier: `Simple view example`_
|
|
|
|
When should you use ``form_for_model()`` and ``form_for_instance()``?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
|
|
shortcuts for the common case. If you want to create a form whose fields map to
|
|
more than one model, or a form that contains fields that *aren't* on a model,
|
|
you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
|
|
isn't that difficult, after all.
|
|
|
|
More coming soon
|
|
================
|
|
|
|
That's all the documentation for now. For more, see the file
|
|
http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms
|
|
-- the unit tests for ``django.newforms``. This can give you a good idea of
|
|
what's possible. (Each submodule there contains separate tests.)
|
|
|
|
If you're really itching to learn and use this library, please be patient.
|
|
We're working hard on finishing both the code and documentation.
|