Fixed #22796 -- Added a more basic explanations of forms.

Thanks bmispelon, kezabelle, jorgecarleitao, and timgraham for reviews.
This commit is contained in:
Daniele Procida 2014-06-08 19:30:52 +01:00 committed by Tim Graham
parent dbbcfca476
commit cd20b5d186
4 changed files with 505 additions and 215 deletions

View File

@ -376,6 +376,8 @@ 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 their name) or for the form as a whole (considering combinations of various
fields). More information about this is in :doc:`/ref/forms/validation`. fields). More information about this is in :doc:`/ref/forms/validation`.
.. _ref-forms-api-outputting-html:
Outputting forms as HTML Outputting forms as HTML
------------------------ ------------------------
@ -492,6 +494,8 @@ it calls its ``as_table()`` method behind the scenes::
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr> <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" 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> <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
.. _ref-forms-api-styling-form-rows:
Styling required or erroneous form rows Styling required or erroneous form rows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,3 +1,4 @@
à
Aalto Aalto
accessor accessor
Aceh Aceh
@ -153,6 +154,7 @@ dirmod
distro distro
divisibleby divisibleby
django django
Django's
djangojs djangojs
djangonaut djangonaut
djangoproject djangoproject

View File

@ -56,7 +56,7 @@ Using initial data with a formset
Initial data is what drives the main usability of a formset. As shown above Initial data is what drives the main usability of a formset. As shown above
you can define the number of extra forms. What this means is that you are you can define the number of extra forms. What this means is that you are
telling the formset how many additional forms to show in addition to the telling the formset how many additional forms to show in addition to the
number of forms it generates from the initial data. Lets take a look at an number of forms it generates from the initial data. Let's take a look at an
example:: example::
>>> import datetime >>> import datetime

View File

@ -2,128 +2,372 @@
Working with forms Working with forms
================== ==================
.. currentmodule:: django.forms
.. admonition:: About this document .. admonition:: About this document
This document provides an introduction to Django's form handling features. This document provides an introduction to the basics of web forms and how
For a more detailed look at specific areas of the forms API, see they are handled in Django. For a more detailed look at specific areas of
:doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and the forms API, see :doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and
:doc:`/ref/forms/validation`. :doc:`/ref/forms/validation`.
.. highlightlang:: html+django Unless you're planning to build websites and applications that do nothing but
publish content, and don't accept input from your visitors, you're going to
need to understand and use forms.
``django.forms`` is Django's form-handling library. Django provides a range of tools and libraries to help you build forms to
accept input from site visitors, and process and respond to the input.
While it is possible to process form submissions just using Django's HTML forms
:class:`~django.http.HttpRequest` class, using the form library takes care of a ==========
number of common form-related tasks. Using it, you can:
1. Display an HTML form with automatically generated form widgets. In HTML, a form is a collection of elements inside ``<form>...</form>`` that
2. Check submitted data against a set of validation rules. allow a visitor to do things like enter text, select options, manipulate
3. Redisplay a form in the case of validation errors. objects or controls, and so on, and then send that information back to the
4. Convert submitted form data to the relevant Python data types. server.
Overview Some of these form interface elements - text input or checkboxes - are fairly
======== simple and built-in to HTML itself. Others are much more complex; an interface
that pops up a date picker or allows you to move a slider or manipulate
controls will typically use JavaScript and CSS as well as HTML form ``<input>``
elements to achieve these effects.
The library deals with these concepts: As well as its ``<input>`` elements, a form must specify two things:
.. glossary:: * *where*: the URL to which the data corresponding to the user's input should
be returned
Widget * *how*: the HTTP method the data should be returned by
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 As an example, the standard Django login form contains several ``<input>``
A class that is responsible for doing validation, e.g. elements: one of ``type="text"`` for the username, one of ``type="password"``
an ``EmailField`` that makes sure its data is a valid email address. for the password, and one of one of ``type="submit"`` for the "Log in" button.
It also contains some hidden text fields that the user doesn't see, that Django
uses to determine what to do next.
Form It also tells the browser that the form data should be sent to the URL
A collection of fields that knows how to validate itself and specified in the ``<form>``s ``action`` attribute - ``/admin/`` - and that it
display itself as HTML. should be sent using the HTTP mechanism specified by the ``method`` attribute -
``post``.
Form Assets (the ``Media`` class) When the ``<input type="submit" value="Log in">`` element is triggered, the
The CSS and JavaScript resources that are required to render a form. data are returned to ``/admin/``.
The library is decoupled from the other Django components, such as the database ``GET`` and ``POST``
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 ``GET`` and ``POST`` are the only HTTP methods to use when dealing with forms.
============
A Form object encapsulates a sequence of form fields and a collection of Django's login form is returned using the ``POST`` method, in which the browser
validation rules that must be fulfilled in order for the form to be accepted. bundles up the form data, encodes them for transmission, sends them back to
Form classes are created as subclasses of ``django.forms.Form`` and the server, and then receives its response.
make use of a declarative style that you'll be familiar with if you've used
Django's database models.
For example, consider a form used to implement "contact me" functionality on a ``GET`` by contrast bundles the submitted data into a string, and uses this to
personal Web site: compose a URL. The URL contains the address where the data must be sent, as
well as the data keys and values. You can see this in action if you do a search
in the Django documentation, which will produce a URL of the form
``https://docs.djangoproject.com/search/?q=forms&release=1``.
``GET`` and ``POST`` are typically used for different purposes.
Any request that could be used to change the state of the system - for example,
a request that makes changes in the database - should use ``POST``. ``GET``
should be used only for requests that do not affect the state of the system.
``GET`` would also be unsuitable for a password form, because the password
would appear in the URL, and thus also in browser history and server logs,
all in plaintext. Neither would it be suitable for large quantities of data,
or for binary data, such as an image. A web application that uses ``GET``
requests for admin forms is a security risk: it can be easy for an attacker to
mimic a form's request to gain access to sensitive parts of the system.
``POST``, coupled with other protections like Django's:doc:`CSRF protection
</ref/contrib/csrf/>` offers more control over access.
On the other hand, ``GET`` is suitable for things like a web search form,
because the URLs that represent a ``GET`` request can easily be bookmarked,
shared, or resubmitted.
Django's role in forms
======================
Handling forms is a complex business. Consider Django's admin, where numerous
items of data of various different types may need to be prepared for display in
a form, rendered as HTML, edited using a convenient interface, returned to the
server, validated and cleaned up, and then saved or passed on for further
processing.
Django's form functionality can simplify and automate vast portions of this
work, and also do it more safely and securely than most programmers would be
able to do in code they wrote themselves.
Django handles three distinct parts of the work involved in forms.
* preparing and restructuring data ready for rendering
* creating HTML forms for the data
* receiving and processing submitted forms and data from the client
It's *possible* to write code that does all of this manually, but Django can
take care of it all for you.
Forms in Django
===============
We've described HTML forms briefly, but an HTML ``<form>`` is just one part of
the machinery required.
In the context of a web application, 'form' might refer to that HTML
``<form>``, or to the Django :class:`Form` that produces it, or to the
structured data returned when it is submitted, or to the end-to-end working
collection of these parts.
The Django :class:`Form` class
------------------------------
At the heart of this system of components is Django's :class:`Form` class. In
much the same way that a Django model describes the logical structure of an
object, its behavior, and the way its parts are represented to us, a
:class:`Form` class describes a form and determines how it works and appears.
In a similar way that a model class's fields map to database fields, a form
class's fields map to HTML form ``<input>`` elements. (A :class:`ModelForm`
maps a model class's fields to HTML form ``<input>`` elements via a
:class:`Form`; this is what the Django admin is based upon.)
A form's fields are themselves classes; they manage form data and perform
validation when a form is submitted. A ``DateField`` and a ``FileField`` handle
very different kinds of data and have to do different things with them.
A form field is represented to a user in the browser as a HTML "widget" - a
piece of user interface machinery. Each field type has an appropriate default
:doc:`Widget class </ref/forms/widgets/>`, but these can be overridden as
required.
Instantiating, processing, and rendering forms
----------------------------------------------
When rendering an object in Django we generally:
1. get hold of it in the view (fetch it from the database, for example)
2. pass it to the template context
3. expand it to HTML markup using template variables
Rendering a form in a template involves nearly the same work as rendering any
other kind of object, but there are some key differences.
In the case of a model instance that contained no data it would rarely if ever
be useful to do anything with one in a template. On the other hand, it makes
perfect sense to render an unpopulated form - that's what we do when we want
the user to populate it.
So when we handle a model instance in a view we typically retrieve it from the
database; when we're dealing with a form we typically instantiate it in the
view.
When we instantiate a form, we can opt to leave it empty or pre-populate it, for
example with:
* data from a saved model instance (as in the case of admin forms for editing)
* data that we have collated from other sources
* data received from a previous HTML form submission
The last of these cases is the most interesting, because it's what makes it
possible for users not just to read a website, but to send information back to
it too.
Building a form
===============
The work that needs to done
---------------------------
Suppose you want to create a simple form on your website, to obtain the user's
name. You'd need something like this in your template:
.. code-block:: html+django
<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
This tells the browser to return the form data to the URL ``/your-name/``, using
the ``POST`` method. It will display a text field, labeled "Your name:", and a
button marked "OK". If the template context contains a ``current_name``
variable, that will be used to pre-fill the ``your_name`` field.
You'll need a view that renders the template containing the HTML form, and
that can supply the ``current_name`` field as appropriate.
When the form is submitted, the ``POST`` request sent to the server will contain
the form data.
Now you'll also need a view corresponding to that ``/your-name/`` URL which will
find the appropriate key/value pairs in the request and process them.
This is a very simple form. In practice, a form might contain dozens or
hundreds of fields, many of which might need to be pre-populated, and we might
expect the user to work through the edit-submit cycle several times before
concluding the operation.
We might require some validation to occur in the browser, even before the form
is submitted; we might want to use much more complex fields, that allow the
user to do things like pick dates from a calendar; and so on.
At this point it's much easier to get Django to do most of this work for us.
Building a form in Django
-------------------------
The :class:`Form` class
^^^^^^^^^^^^^^^^^^^^^^^
We already know what we want our HTML form to look like. Our starting point for
it in Django is this:
.. code-block:: python .. code-block:: python
from django import forms from django import forms
class ContactForm(forms.Form): class NameForm(forms.Form):
subject = forms.CharField(max_length=100) your_name = forms.CharField(label='Your name', max_length=100)
message = forms.CharField()
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
A form is composed of ``Field`` objects. In this case, our form has four This defines a :class:`Form` class with a single field (``your_name``). We've
fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. ``CharField``, applied a human-friendly label to the field, that will appear in the
``EmailField`` and ``BooleanField`` are just three of the available field types; ``<label>`` when it's rendered (although in this case, the :attr:`~Field.label`
a full list can be found in :doc:`/ref/forms/fields`. we specified is actually the same one that would be generated automatically if
we had omitted it).
If your form is going to be used to directly add or edit a Django model, you can The field's maximum allowable length is defined by
use a :doc:`ModelForm </topics/forms/modelforms>` to avoid duplicating your model :attr:`~CharField.max_length`. This does two things. It puts a
description. ``maxlength="100"`` on the HTML ``<input>`` (so the browser should prevent the
user entering more than that many characters in the first place). It also means
that when Django receives the form back from the browser, it will validate the
length of the data.
A :class:`Form` instance has an :meth:`~Form.is_valid()` method, which runs
validation routines for all its fields. When this method is called, if all
fields contain valid data, it will:
* return ``True``
* place the form's data in its :attr:`~Form.cleaned_data` attribute.
The whole form, when rendered for the first time, will look like:
.. code-block:: html+django
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">
Note that it **does not** include the ``<form>`` tags, or a submit button.
We'll have to provide those ourselves in the template.
.. _using-a-form-in-a-view: .. _using-a-form-in-a-view:
Using a form in a view The view
---------------------- ^^^^^^^^
The standard pattern for processing a form in a view looks like this: Form data sent back to a Django website are processed by a view, generally the
same view that published the form. This allows us to reuse some of the same
logic.
To handle the form we need to instantiate it in the view for the URL where we
want it to be published:
.. code-block:: python .. code-block:: python
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
def contact(request): def get_name(request):
if request.method == 'POST': # If the form has been submitted... # if this is a POST request we need to process the form data
# ContactForm was defined in the previous section if request.method == 'POST':
form = ContactForm(request.POST) # A form bound to the POST data # create a form instance and populate it with data from the request:
if form.is_valid(): # All validation rules pass form = NameForm(request.POST)
# Process the data in form.cleaned_data # check whether it's valid:
# ... if form.is_valid():
return HttpResponseRedirect('/thanks/') # Redirect after POST # process the data in form.cleaned_data as required
else: # ...
form = ContactForm() # An unbound form # redirect to a new URL:
return HttpResponseRedirect('/thanks/')
return render(request, 'contact.html', { # if a GET (or any other method) we'll create a blank form
'form': form, else:
}) form = NameForm()
return render(request, 'name.html', {'form': form})
There are three possible code paths here: If we arrive at this view with a ``GET`` request, it will create an empty form
instance and place it in the template context to be rendered. This is what we
can expect to happen the first time we visit the URL.
+------------------+---------------+-----------------------------------------+ If the form is submitted using a ``POST`` request, the view will once again
| Form submitted? | Data? | What occurs | create a form instance and populate it with data from the request: ``form =
+==================+===============+=========================================+ NameForm(request.POST)`` (this is called "binding data to the form" - it is now
| Not submitted | None yet | Template gets passed unbound instance | a *bound* form).
| | | of ContactForm. |
+------------------+---------------+-----------------------------------------+ We call the form's ``is_valid()`` method; if it's not ``True``, we go back to
| Submitted | Invalid data | Template gets passed bound instance | the template with the form. This time the form is no longer empty (*unbound*)
| | | of ContactForm. | so the HTML form will be populated with the data previously submitted, where it
+------------------+---------------+-----------------------------------------+ can be edited and corrected as required.
| Submitted | Valid data | Valid data is processed. Redirect to a |
| | | "thanks" page. | If ``is_valid()`` is ``True``, we'll now be able to find all the validated form
+------------------+---------------+-----------------------------------------+ data in its ``cleaned_data`` attribute. We can use these data to update the
database or do other processing before sending an HTTP redirect to the browser
telling it where to go next.
.. _topics-forms-index-basic-form-template:
The template
^^^^^^^^^^^^
We don't need to do much in our ``name.html`` template. The simplest example
is:
.. code-block:: html+django
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
All the form's fields and their attributes will be unpacked into HTML markup
from that ``{{ form }}`` by Django's template language.
.. admonition:: Forms and Cross Site Request Forgery protection
Django ships with an easy-to-use :doc:`protection against Cross Site Request
Forgeries </ref/contrib/csrf>`. When submitting a form via ``POST`` with
CSRF protection enabled you must use the :ttag:`csrf_token` template tag
as in the preceding example. However, since CSRF protection is not
directly tied to forms in templates, this tag is omitted from the
following examples in this document.
We now have a working web form, described by a Django :class:`Form`, processed
by a view, and rendered as an HTML ``<form>``.
That's all you need to get started, but the forms framework puts a lot more at
your fingertips. Once you understand the basics of the process described above,
you should be aware of what else is readily available in the forms system
and know a little bit about some of the underlying machinery.
More about Django :class:`Form` classes
=======================================
All form classes are created as subclasses of ``django.forms.Form``, including
the :doc:`ModelForm </topics/forms/modelforms>` you encounter in Django's
admin.
.. admonition:: Models and Forms
In fact if your form is going to be used to directly add or edit a Django
model, a :doc:`ModelForm </topics/forms/modelforms>` can save you a great
deal of time, effort, and code, because it will build a form, along with the
appropriate fields and their attributes, from a ``Model`` class.
Bound and unbound form instances
--------------------------------
The distinction between :ref:`ref-forms-api-bound-unbound` is important: The distinction between :ref:`ref-forms-api-bound-unbound` is important:
@ -134,37 +378,67 @@ The distinction between :ref:`ref-forms-api-bound-unbound` is important:
is valid. If an invalid bound form is rendered, it can include inline error is valid. If an invalid bound form is rendered, it can include inline error
messages telling the user what data to correct. messages telling the user what data to correct.
Handling file uploads with a form The form's ``is_bound()`` method will tell you whether a form has data bound to
--------------------------------- it or not.
To see how to handle file uploads with your form, see More on fields
:ref:`binding-uploaded-files`. --------------
Processing the data from a form Consider a rather more useful form than our minimal example above, that
------------------------------- we could use to implement "contact me" functionality on a personal Web site:
Once ``is_valid()`` returns ``True``, the successfully validated form data .. code-block:: python
will be in the ``form.cleaned_data`` dictionary. This data will have been
converted nicely into Python types for you. from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
Our earlier form used a single field, ``your_name``, a ``CharField``. In this
case, our form has four fields: ``subject``, ``message``, ``sender`` and
``cc_myself``. :class:`CharField`, :class:`EmailField` and
:class:`BooleanField` are just three of the available field types; a full list
can be found in :doc:`/ref/forms/fields`.
Widgets
^^^^^^^
Each form field has a corresponding :doc:`Widget class </ref/forms/widgets/>`,
which in turn corresponds to an HTML form widget such as ``<input
type="text">``.
In most cases, the field will have a sensible default widget. For example, by
default, a ``CharField`` will have a :class:`TextInput` widget, that produces an
``<input type="text">`` in the HTML. If you needed ``<input type="textarea">``
instead, you'd specify the appropriate widget when defining your form field,
as we have done for the ``message`` field.
Field data
^^^^^^^^^^
Whatever the data submitted with a form, once it has been successfully
validated by calling ``is_valid()`` (and ``is_valid()`` has returned ``True``),
the validated form data will be in the ``form.cleaned_data`` dictionary. This
data will have been converted nicely into Python types for you.
.. note:: .. note::
You can still access the unvalidated data directly from ``request.POST`` at You can still access the unvalidated data directly from ``request.POST`` at
this point, but the validated data is better. this point, but the validated data is better.
In the above example, ``cc_myself`` will be a boolean value. Likewise, fields In the contact form example above, ``cc_myself`` will be a boolean value.
such as ``IntegerField`` and ``FloatField`` convert values to a Python int and Likewise, fields such as :class:`IntegerField` and :class:`FloatField` convert
float respectively. values to a Python ``int`` and ``float`` respectively.
Read-only fields are not available in ``form.cleaned_data`` (and setting Here's how the form data could be processed in the view that handles this form:
a value in a custom ``clean()`` method won't have any effect). These
fields are displayed as text rather than as input elements, and thus are not
posted back to the server.
Extending the earlier example, here's how the form data could be processed:
.. code-block:: python .. code-block:: python
from django.core.mail import send_mail
if form.is_valid(): if form.is_valid():
subject = form.cleaned_data['subject'] subject = form.cleaned_data['subject']
message = form.cleaned_data['message'] message = form.cleaned_data['message']
@ -175,50 +449,51 @@ Extending the earlier example, here's how the form data could be processed:
if cc_myself: if cc_myself:
recipients.append(sender) recipients.append(sender)
from django.core.mail import send_mail
send_mail(subject, message, sender, recipients) send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/') # Redirect after POST return HttpResponseRedirect('/thanks/')
.. tip:: .. tip::
For more on sending email from Django, see :doc:`/topics/email`. For more on sending email from Django, see :doc:`/topics/email`.
Displaying a form using a template Some field types need some extra handling. For example, files that are uploaded
---------------------------------- using a form need to be handled differently (they can be retrieved from
``request.FILES``, rather than ``request.POST``). For details of how to handle
file uploads with your form, see :ref:`binding-uploaded-files`.
Forms are designed to work with the Django template language. In the above Working with form templates
example, we passed our ``ContactForm`` instance to the template using the ===========================
context variable ``form``. Here's a simple example template::
<form action="/contact/" method="post">{% csrf_token %} All you need to do to get your form into a template is to place the form
{{ form.as_p }} instance into the template context. So if your form is called ``form`` in the
<input type="submit" value="Submit" /> context, ``{{ form }}`` will render its ``<label>`` and ``<input>`` elements
</form> appropriately.
The form only outputs its own fields; it is up to you to provide the surrounding Form rendering options
``<form>`` tags and the submit button. ----------------------
If your form includes uploaded files, be sure to include .. admonition:: Additional form template furniture
``enctype="multipart/form-data"`` in the ``form`` element. If you wish to write
a generic template that will work whether or not the form has files, you can
use the :meth:`~django.forms.Form.is_multipart` attribute on the form::
<form action="/contact/" method="post" Don't forget that a form's output does *not* include the surrounding
{% if form.is_multipart %}enctype="multipart/form-data"{% endif %}> ``<form>`` tags, or the form's ``submit`` control. You will have to provide
these yourself.
.. admonition:: Forms and Cross Site Request Forgery protection There are other output options though for the ``<label>``/``<input>`` pairs:
Django ships with an easy-to-use :doc:`protection against Cross Site Request * ``{{ form.as_table }}`` will render them as table cells wrapped in ``<tr>``
Forgeries </ref/contrib/csrf>`. When submitting a form via POST with tags
CSRF protection enabled you must use the :ttag:`csrf_token` template tag
as in the preceding example. However, since CSRF protection is not
directly tied to forms in templates, this tag is omitted from the
following examples in this document.
``form.as_p`` will output the form with each form field and accompanying label * ``{{ form.as_p }}`` will render them wrapped in ``<p>`` tags
wrapped in a paragraph. Here's the output for our example template::
* ``{{ form.as_ul }}`` will render them wrapped in ``<li>`` tags
Note that you'll have to provide the surrounding ``<table>`` or ``<ul>``
elements yourself.
Here's the output of ``{{ form.as_p }}`` for our ``ContactForm`` instance:
.. code-block:: html+django
<form action="/contact/" method="post">
<p><label for="id_subject">Subject:</label> <p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" /></p> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_message">Message:</label> <p><label for="id_message">Message:</label>
@ -227,8 +502,6 @@ wrapped in a paragraph. Here's the output for our example template::
<input type="email" name="sender" id="id_sender" /></p> <input type="email" name="sender" id="id_sender" /></p>
<p><label for="id_cc_myself">Cc myself:</label> <p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
<input type="submit" value="Submit" />
</form>
Note that each form field has an ID attribute set to ``id_<field-name>``, which Note that each form field has an ID attribute set to ``id_<field-name>``, which
is referenced by the accompanying label tag. This is important for ensuring is referenced by the accompanying label tag. This is important for ensuring
@ -236,45 +509,53 @@ forms are accessible to assistive technology such as screen reader software. You
can also :ref:`customize the way in which labels and ids are generated can also :ref:`customize the way in which labels and ids are generated
<ref-forms-api-configuring-label>`. <ref-forms-api-configuring-label>`.
You can also use ``form.as_table`` to output table rows (you'll need to provide See :ref:`ref-forms-api-outputting-html` for more on this.
your own ``<table>`` tags) and ``form.as_ul`` to output list items.
Customizing the form template Rendering fields manually
----------------------------- -------------------------
If the default generated HTML is not to your taste, you can completely customize We don't have to let Django unpack the form's fields; we can do it manually if
the way a form is presented using the Django template language. Extending the we like (allowing us to reorder the fields, for example). Each field is
above example:: available as an attribute of the form using ``{{ form.name_of_field }}``, and
in a Django template, will be rendered appropriately. For example:
<form action="/contact/" method="post"> .. code-block:: html+django
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
Each named form-field can be output to the template using {{ form.non_field_errors }}
``{{ form.name_of_field }}``, which will produce the HTML needed to display the <div class="fieldWrapper">
form widget. Using ``{{ form.name_of_field.errors }}`` displays a list of form {{ form.subject.errors }}
errors, rendered as an unordered list. This might look like:: <label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
Rendering form error messages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The price of this flexibility of course is more work. Until now we haven't had
to worry about how to display form errors, because that's taken care of for us.
In this example we have had to make sure we take care of any errors for each
field and any errors for the form as a whole. Note ``{{ form.non_field_errors
}}`` at the top of the form and the template lookup for errors on each field.
Using ``{{ form.name_of_field.errors }}`` displays a list of form errors,
rendered as an unordered list. This might look like:
.. code-block:: html+django
<ul class="errorlist"> <ul class="errorlist">
<li>Sender is required.</li> <li>Sender is required.</li>
@ -282,7 +563,9 @@ errors, rendered as an unordered list. This might look like::
The list has a CSS class of ``errorlist`` to allow you to style its appearance. The list has a CSS class of ``errorlist`` to allow you to style its appearance.
If you wish to further customize the display of errors you can do so by looping If you wish to further customize the display of errors you can do so by looping
over them:: over them:
.. code-block:: html+django
{% if form.subject.errors %} {% if form.subject.errors %}
<ol> <ol>
@ -297,32 +580,34 @@ over them::
Non-field errors (and/or hidden field errors that are rendered at the top of Non-field errors (and/or hidden field errors that are rendered at the top of
the form when using helpers like ``form.as_p()``) will be rendered with an the form when using helpers like ``form.as_p()``) will be rendered with an
additional class of ``nonfield`` to help distinguish them from field-specific additional class of ``nonfield`` to help distinguish them from field-specific
errors. For example, ``{{ form.non_field_errors }}`` would look like:: errors. For example, ``{{ form.non_field_errors }}`` would look like:
.. code-block:: html+django
<ul class="errorlist nonfield"> <ul class="errorlist nonfield">
<li>Generic validation error</li> <li>Generic validation error</li>
</ul> </ul>
See :doc:`/ref/forms/api` for more on errors, styling, and working with form
attributes in templates.
Looping over the form's fields Looping over the form's fields
------------------------------ ------------------------------
If you're using the same HTML for each of your form fields, you can reduce If you're using the same HTML for each of your form fields, you can reduce
duplicate code by looping through each field in turn using a ``{% for %}`` duplicate code by looping through each field in turn using a ``{% for %}``
loop:: loop:
<form action="/contact/" method="post"> .. code-block:: html+django
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
Within this loop, ``{{ field }}`` is an instance of {% for field in form %}
:class:`~django.forms.BoundField`. ``BoundField`` also has the following <div class="fieldWrapper">
attributes, which can be useful in your templates: {{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
Useful attributes on ``{{ field }}`` include:
``{{ field.label }}`` ``{{ field.label }}``
The label of the field, e.g. ``Email address``. The label of the field, e.g. ``Email address``.
@ -341,7 +626,7 @@ attributes, which can be useful in your templates:
some inline JavaScript and want to avoid hardcoding the field's ID. some inline JavaScript and want to avoid hardcoding the field's ID.
``{{ field.value }}`` ``{{ field.value }}``
The value of the field. e.g ``someone@example.com`` The value of the field. e.g ``someone@example.com``.
``{{ field.html_name }}`` ``{{ field.html_name }}``
The name of the field that will be used in the input element's name The name of the field that will be used in the input element's name
@ -360,7 +645,9 @@ attributes, which can be useful in your templates:
``{{ field.is_hidden }}`` ``{{ field.is_hidden }}``
This attribute is ``True`` if the form field is a hidden field and This attribute is ``True`` if the form field is a hidden field and
``False`` otherwise. It's not particularly useful as a template ``False`` otherwise. It's not particularly useful as a template
variable, but could be useful in conditional tests such as:: variable, but could be useful in conditional tests such as:
.. code-block:: html+django
{% if field.is_hidden %} {% if field.is_hidden %}
{# Do something special #} {# Do something special #}
@ -373,11 +660,11 @@ attributes, which can be useful in your templates:
``{{ char_field.field.max_length }}``. ``{{ char_field.field.max_length }}``.
Looping over hidden and visible fields Looping over hidden and visible fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you're manually laying out a form in a template, as opposed to relying on If you're manually laying out a form in a template, as opposed to relying on
Django's default form layout, you might want to treat ``<input type="hidden">`` Django's default form layout, you might want to treat ``<input type="hidden">``
fields differently than non-hidden fields. For example, because hidden fields fields differently from non-hidden fields. For example, because hidden fields
don't display anything, putting error messages "next to" the field could cause don't display anything, putting error messages "next to" the field could cause
confusion for your users -- so errors for those fields should be handled confusion for your users -- so errors for those fields should be handled
differently. differently.
@ -385,22 +672,21 @@ differently.
Django provides two methods on a form that allow you to loop over the hidden Django provides two methods on a form that allow you to loop over the hidden
and visible fields independently: ``hidden_fields()`` and and visible fields independently: ``hidden_fields()`` and
``visible_fields()``. Here's a modification of an earlier example that uses ``visible_fields()``. Here's a modification of an earlier example that uses
these two methods:: these two methods:
<form action="/contact/" method="post"> .. code-block:: html+django
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %} {# Include the hidden fields #}
{{ hidden }} {% for hidden in form.hidden_fields %}
{% endfor %} {{ hidden }}
{# Include the visible fields #} {% endfor %}
{% for field in form.visible_fields %} {# Include the visible fields #}
<div class="fieldWrapper"> {% for field in form.visible_fields %}
{{ field.errors }} <div class="fieldWrapper">
{{ field.label_tag }} {{ field }} {{ field.errors }}
</div> {{ field.label_tag }} {{ field }}
{% endfor %} </div>
<p><input type="submit" value="Send message" /></p> {% endfor %}
</form>
This example does not handle any errors in the hidden fields. Usually, an This example does not handle any errors in the hidden fields. Usually, an
error in a hidden field is a sign of form tampering, since normal form error in a hidden field is a sign of form tampering, since normal form
@ -412,15 +698,14 @@ Reusable form templates
If your site uses the same rendering logic for forms in multiple places, you If your site uses the same rendering logic for forms in multiple places, you
can reduce duplication by saving the form's loop in a standalone template and can reduce duplication by saving the form's loop in a standalone template and
using the :ttag:`include` tag to reuse it in other templates:: using the :ttag:`include` tag to reuse it in other templates:
<form action="/contact/" method="post"> .. code-block:: html+django
{% include "form_snippet.html" %}
<p><input type="submit" value="Send message" /></p> # In your form template:
</form> {% include "form_snippet.html" %}
# In form_snippet.html: # In form_snippet.html:
{% for field in form %} {% for field in form %}
<div class="fieldWrapper"> <div class="fieldWrapper">
{{ field.errors }} {{ field.errors }}
@ -430,12 +715,11 @@ using the :ttag:`include` tag to reuse it in other templates::
If the form object passed to a template has a different name within the If the form object passed to a template has a different name within the
context, you can alias it using the ``with`` argument of the :ttag:`include` context, you can alias it using the ``with`` argument of the :ttag:`include`
tag:: tag:
<form action="/comments/add/" method="post"> .. code-block:: html+django
{% include "form_snippet.html" with form=comment_form %}
<p><input type="submit" value="Submit comment" /></p> {% include "form_snippet.html" with form=comment_form %}
</form>
If you find yourself doing this often, you might consider creating a custom If you find yourself doing this often, you might consider creating a custom
:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`. :ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`.