| 1 |
============ |
|---|
| 2 |
Form preview |
|---|
| 3 |
============ |
|---|
| 4 |
|
|---|
| 5 |
Django comes with an optional "form preview" application that helps automate |
|---|
| 6 |
the following workflow: |
|---|
| 7 |
|
|---|
| 8 |
"Display an HTML form, force a preview, then do something with the submission." |
|---|
| 9 |
|
|---|
| 10 |
To force a preview of a form submission, all you have to do is write a short |
|---|
| 11 |
Python class. |
|---|
| 12 |
|
|---|
| 13 |
Overview |
|---|
| 14 |
========= |
|---|
| 15 |
|
|---|
| 16 |
Given a ``django.newforms.Form`` subclass that you define, this application |
|---|
| 17 |
takes care of the following workflow: |
|---|
| 18 |
|
|---|
| 19 |
1. Displays the form as HTML on a Web page. |
|---|
| 20 |
2. Validates the form data when it's submitted via POST. |
|---|
| 21 |
a. If it's valid, displays a preview page. |
|---|
| 22 |
b. If it's not valid, redisplays the form with error messages. |
|---|
| 23 |
3. When the "confirmation" form is submitted from the preview page, calls |
|---|
| 24 |
a hook that you define -- a ``done()`` method that gets passed the valid |
|---|
| 25 |
data. |
|---|
| 26 |
|
|---|
| 27 |
The framework enforces the required preview by passing a shared-secret hash to |
|---|
| 28 |
the preview page via hidden form fields. If somebody tweaks the form parameters |
|---|
| 29 |
on the preview page, the form submission will fail the hash-comparison test. |
|---|
| 30 |
|
|---|
| 31 |
How to use ``FormPreview`` |
|---|
| 32 |
========================== |
|---|
| 33 |
|
|---|
| 34 |
1. Point Django at the default FormPreview templates. There are two ways to |
|---|
| 35 |
do this: |
|---|
| 36 |
|
|---|
| 37 |
* Add ``'django.contrib.formtools'`` to your ``INSTALLED_APPS`` |
|---|
| 38 |
setting. This will work if your ``TEMPLATE_LOADERS`` setting includes |
|---|
| 39 |
the ``app_directories`` template loader (which is the case by |
|---|
| 40 |
default). See the `template loader docs`_ for more. |
|---|
| 41 |
|
|---|
| 42 |
* Otherwise, determine the full filesystem path to the |
|---|
| 43 |
``django/contrib/formtools/templates`` directory, and add that |
|---|
| 44 |
directory to your ``TEMPLATE_DIRS`` setting. |
|---|
| 45 |
|
|---|
| 46 |
2. Create a ``FormPreview`` subclass that overrides the ``done()`` method:: |
|---|
| 47 |
|
|---|
| 48 |
from django.contrib.formtools.preview import FormPreview |
|---|
| 49 |
from myapp.models import SomeModel |
|---|
| 50 |
|
|---|
| 51 |
class SomeModelFormPreview(FormPreview): |
|---|
| 52 |
|
|---|
| 53 |
def done(self, request, cleaned_data): |
|---|
| 54 |
# Do something with the cleaned_data, then redirect |
|---|
| 55 |
# to a "success" page. |
|---|
| 56 |
return HttpResponseRedirect('/form/success') |
|---|
| 57 |
|
|---|
| 58 |
This method takes an ``HttpRequest`` object and a dictionary of the form |
|---|
| 59 |
data after it has been validated and cleaned. It should return an |
|---|
| 60 |
``HttpResponseRedirect`` that is the end result of the form being |
|---|
| 61 |
submitted. |
|---|
| 62 |
|
|---|
| 63 |
3. Change your URLconf to point to an instance of your ``FormPreview`` |
|---|
| 64 |
subclass:: |
|---|
| 65 |
|
|---|
| 66 |
from myapp.preview import SomeModelFormPreview |
|---|
| 67 |
from myapp.models import SomeModel |
|---|
| 68 |
from django import newforms as forms |
|---|
| 69 |
|
|---|
| 70 |
...and add the following line to the appropriate model in your URLconf:: |
|---|
| 71 |
|
|---|
| 72 |
(r'^post/$', SomeModelFormPreview(SomeModelForm)), |
|---|
| 73 |
|
|---|
| 74 |
where ``SomeModelForm`` is a Form or ModelForm class for the model. |
|---|
| 75 |
|
|---|
| 76 |
4. Run the Django server and visit ``/post/`` in your browser. |
|---|
| 77 |
|
|---|
| 78 |
.. _template loader docs: ../templates_python/#loader-types |
|---|
| 79 |
|
|---|
| 80 |
``FormPreview`` classes |
|---|
| 81 |
======================= |
|---|
| 82 |
|
|---|
| 83 |
A ``FormPreview`` class is a simple Python class that represents the preview |
|---|
| 84 |
workflow. ``FormPreview`` classes must subclass |
|---|
| 85 |
``django.contrib.formtools.preview.FormPreview`` and override the ``done()`` |
|---|
| 86 |
method. They can live anywhere in your codebase. |
|---|
| 87 |
|
|---|
| 88 |
``FormPreview`` templates |
|---|
| 89 |
========================= |
|---|
| 90 |
|
|---|
| 91 |
By default, the form is rendered via the template ``formtools/form.html``, and |
|---|
| 92 |
the preview page is rendered via the template ``formtools.preview.html``. |
|---|
| 93 |
These values can be overridden for a particular form preview by setting |
|---|
| 94 |
``preview_template`` and ``form_template`` attributes on the FormPreview |
|---|
| 95 |
subclass. See ``django/contrib/formtools/templates`` for the default templates. |
|---|