mirror of
https://github.com/django/django.git
synced 2024-12-23 01:25:58 +00:00
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:
parent
b4f5e80cd1
commit
6154d58cb5
@ -47,36 +47,34 @@ 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.
|
||||
|
||||
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.
|
||||
|
||||
1. Define a number of :class:`~django.forms.Form` classes -- one per wizard
|
||||
page.
|
||||
|
||||
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
|
||||
the message itself. Here's what the :file:`forms.py` might look like::
|
||||
|
||||
from django import forms
|
||||
from django import forms
|
||||
|
||||
class ContactForm1(forms.Form):
|
||||
subject = forms.CharField(max_length=100)
|
||||
@ -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.
|
||||
|
||||
* ``request`` -- an :class:`~django.http.HttpRequest` object
|
||||
* ``form_list`` -- a list of :mod:`django.forms`
|
||||
:class:`~django.forms.forms.Form` classes
|
||||
.. 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 :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.
|
||||
|
Loading…
Reference in New Issue
Block a user