Form wizard documentation tweaks:

* Simplified Sphinx references to FormWizard class.
  * Wrapped long lines.
  * Added references to template loader functions.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@11986 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Gary Wilson Jr 2009-12-25 21:07:11 +00:00
parent b4f5e80cd1
commit 6154d58cb5
1 changed files with 73 additions and 79 deletions

View File

@ -47,30 +47,28 @@ Usage
This application handles as much machinery for you as possible. Generally, you
just have to do these things:
1. Define a number of :mod:`django.forms`
:class:`~django.forms.forms.Form` classes -- one per wizard page.
1. Define a number of :class:`~django.forms.Form` classes -- one per wizard
page.
2. Create a :class:`~django.contrib.formtools.wizard.FormWizard` class
that specifies what to do once all of your forms have been submitted
and validated. This also lets you override some of the wizard's behavior.
2. Create a :class:`FormWizard` class that specifies what to do once all of
your forms have been submitted and validated. This also lets you
override some of the wizard's behavior.
3. Create some templates that render the forms. You can define a single,
generic template to handle every one of the forms, or you can define a
specific template for each form.
4. Point your URLconf at your
:class:`~django.contrib.formtools.wizard.FormWizard` class.
4. Point your URLconf at your :class:`FormWizard` class.
Defining ``Form`` classes
=========================
The first step in creating a form wizard is to create the :class:`~django.forms.forms.Form` classes.
These should be standard :mod:`django.forms`
:class:`~django.forms.forms.Form` classes, covered in the
:ref:`forms documentation <topics-forms-index>`.
These classes can live anywhere in your codebase, but convention is to put them
in a file called :file:`forms.py` in your application.
The first step in creating a form wizard is to create the
:class:`~django.forms.Form` classes. These should be standard
:class:`django.forms.Form` classes, covered in the :ref:`forms documentation
<topics-forms-index>`. These classes can live anywhere in your codebase, but
convention is to put them in a file called :file:`forms.py` in your
application.
For example, let's write a "contact form" wizard, where the first page's form
collects the sender's e-mail address and subject, and the second page collects
@ -86,27 +84,27 @@ the message itself. Here's what the :file:`forms.py` might look like::
message = forms.CharField(widget=forms.Textarea)
**Important limitation:** Because the wizard uses HTML hidden fields to store
data between pages, you may not include a :class:`~django.forms.fields.FileField`
data between pages, you may not include a :class:`~django.forms.FileField`
in any form except the last one.
Creating a ``FormWizard`` class
===============================
The next step is to create a :class:`~django.contrib.formtools.wizard.FormWizard`
class, which should be a subclass of ``django.contrib.formtools.wizard.FormWizard``.
As with your :class:`~django.forms.forms.Form` classes, this
:class:`~django.contrib.formtools.wizard.FormWizard` class can live anywhere
in your codebase, but convention is to put it in :file:`forms.py`.
The next step is to create a
:class:`django.contrib.formtools.wizard.FormWizard` subclass. As with your
:class:`~django.forms.Form` classes, this :class:`FormWizard` class can live
anywhere in your codebase, but convention is to put it in :file:`forms.py`.
The only requirement on this subclass is that it implement a
:meth:`~django.contrib.formtools.wizard.FormWizard.done()` method,
which specifies what should happen when the data for *every* form is submitted
and validated. This method is passed two arguments:
:meth:`~FormWizard.done()` method.
.. method:: FormWizard.done
This method specifies what should happen when the data for *every* form is
submitted and validated. This method is passed two arguments:
* ``request`` -- an :class:`~django.http.HttpRequest` object
* ``form_list`` -- a list of :mod:`django.forms`
:class:`~django.forms.forms.Form` classes
* ``form_list`` -- a list of :class:`~django.forms.Form` classes
In this simplistic example, rather than perform any database operation, the
method simply renders a template of the validated data::
@ -133,16 +131,16 @@ example::
return HttpResponseRedirect('/page-to-redirect-to-when-done/')
See the section `Advanced FormWizard methods`_ below to learn about more
:class:`~django.contrib.formtools.wizard.FormWizard` hooks.
:class:`FormWizard` hooks.
Creating templates for the forms
================================
Next, you'll need to create a template that renders the wizard's forms. By
default, every form uses a template called :file:`forms/wizard.html`. (You can
change this template name by overriding
:meth:`~django.contrib.formtools.wizard..get_template()`, which is documented
below. This hook also allows you to use a different template for each form.)
change this template name by overriding :meth:`~FormWizard.get_template()`,
which is documented below. This hook also allows you to use a different
template for each form.)
This template expects the following context:
@ -150,24 +148,20 @@ This template expects the following context:
* ``step0`` -- The current step (zero-based).
* ``step`` -- The current step (one-based).
* ``step_count`` -- The total number of steps.
* ``form`` -- The :class:`~django.forms.forms.Form` instance for the
current step (either empty or with errors).
* ``form`` -- The :class:`~django.forms.Form` instance for the current step
(either empty or with errors).
* ``previous_fields`` -- A string representing every previous data field,
plus hashes for completed forms, all in the form of hidden fields. Note
that you'll need to run this through the
:meth:`~django.template.defaultfilters.safe` template filter, to prevent
auto-escaping, because it's raw HTML.
that you'll need to run this through the :tfilter:`safe` template filter,
to prevent auto-escaping, because it's raw HTML.
It will also be passed any objects in :data:`extra_context`, which is a
dictionary you can specify that contains extra values to add to the context.
You can specify it in two ways:
You can supply extra context to this template in two ways:
* Set the :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context`
attribute on your :class:`~django.contrib.formtools.wizard.FormWizard`
subclass to a dictionary.
* Set the :attr:`~FormWizard.extra_context` attribute on your
:class:`FormWizard` subclass to a dictionary.
* Pass :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context`
as extra parameters in the URLconf.
* Pass a dictionary as a parameter named ``extra_context`` to your wizard's
URL pattern in your URLconf. See :ref:`hooking-wizard-into-urlconf`.
Here's a full example template:
@ -190,12 +184,13 @@ Here's a full example template:
Note that ``previous_fields``, ``step_field`` and ``step0`` are all required
for the wizard to work properly.
.. _hooking-wizard-into-urlconf:
Hooking the wizard into a URLconf
=================================
Finally, give your new :class:`~django.contrib.formtools.wizard.FormWizard`
object a URL in ``urls.py``. The wizard takes a list of your form objects as
arguments::
Finally, give your new :class:`FormWizard` object a URL in ``urls.py``. The
wizard takes a list of your :class:`~django.forms.Form` objects as arguments::
from django.conf.urls.defaults import *
from mysite.testapp.forms import ContactForm1, ContactForm2, ContactWizard
@ -209,19 +204,18 @@ Advanced FormWizard methods
.. class:: FormWizard
Aside from the :meth:`~django.contrib.formtools.wizard.FormWizard.done()`
method, :class:`~django.contrib.formtools.wizard.FormWizard` offers a few
Aside from the :meth:`~done()` method, :class:`FormWizard` offers a few
advanced method hooks that let you customize how your wizard works.
Some of these methods take an argument ``step``, which is a zero-based counter
representing the current step of the wizard. (E.g., the first form is ``0`` and
the second form is ``1``.)
Some of these methods take an argument ``step``, which is a zero-based
counter representing the current step of the wizard. (E.g., the first form
is ``0`` and the second form is ``1``.)
.. method:: FormWizard.prefix_for_step
Given the step, returns a :class:`~django.forms.forms.Form` prefix to
use. By default, this simply uses the step itself. For more, see the
:ref:`form prefix documentation <form-prefix>`.
Given the step, returns a form prefix to use. By default, this simply uses
the step itself. For more, see the :ref:`form prefix documentation
<form-prefix>`.
Default implementation::
@ -237,15 +231,18 @@ Advanced FormWizard methods
def render_hash_failure(self, request, step):
return self.render(self.get_form(step), request, step,
context={'wizard_error': 'We apologize, but your form has expired. Please continue filling out the form from this page.'})
context={'wizard_error':
'We apologize, but your form has expired. Please'
' continue filling out the form from this page.'})
.. method:: FormWizard.security_hash
Calculates the security hash for the given request object and :class:`~django.forms.forms.Form` instance.
Calculates the security hash for the given request object and
:class:`~django.forms.Form` instance.
By default, this uses an MD5 hash of the form data and your
:setting:`SECRET_KEY` setting. It's rare that somebody would need to override
this.
:setting:`SECRET_KEY` setting. It's rare that somebody would need to
override this.
Example::
@ -254,8 +251,8 @@ Advanced FormWizard methods
.. method:: FormWizard.parse_params
A hook for saving state from the request object and ``args`` / ``kwargs`` that
were captured from the URL by your URLconf.
A hook for saving state from the request object and ``args`` / ``kwargs``
that were captured from the URL by your URLconf.
By default, this does nothing.
@ -275,26 +272,23 @@ Advanced FormWizard methods
def get_template(self, step):
return 'myapp/wizard_%s.html' % step
If :meth:`~FormWizard.get_template` returns a list of strings, then the wizard will use the
template system's :func:`~django.template.loader.select_template()`
function,
:ref:`explained in the template docs <ref-templates-api-the-python-api>`.
If :meth:`~FormWizard.get_template` returns a list of strings, then the
wizard will use the template system's
:func:`~django.template.loader.select_template` function.
This means the system will use the first template that exists on the
filesystem. For example::
def get_template(self, step):
return ['myapp/wizard_%s.html' % step, 'myapp/wizard.html']
.. _explained in the template docs: ../templates_python/#the-python-api
.. method:: FormWizard.render_template
Renders the template for the given step, returning an
:class:`~django.http.HttpResponse` object.
Override this method if you want to add a custom context, return a different
MIME type, etc. If you only need to override the template name, use
:meth:`~FormWizard.get_template` instead.
Override this method if you want to add a custom context, return a
different MIME type, etc. If you only need to override the template name,
use :meth:`~FormWizard.get_template` instead.
The template will be rendered with the context documented in the
"Creating templates for the forms" section above.
@ -302,12 +296,12 @@ Advanced FormWizard methods
.. method:: FormWizard.process_step
Hook for modifying the wizard's internal state, given a fully validated
:class:`~django.forms.forms.Form` object. The Form is guaranteed to
have clean, valid data.
:class:`~django.forms.Form` object. The Form is guaranteed to have clean,
valid data.
This method should *not* modify any of that data. Rather, it might want to set
``self.extra_context`` or dynamically alter ``self.form_list``, based on
previously submitted forms.
This method should *not* modify any of that data. Rather, it might want to
set ``self.extra_context`` or dynamically alter ``self.form_list``, based
on previously submitted forms.
Note that this method is called every time a page is rendered for *all*
submitted steps.