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