diff --git a/AUTHORS b/AUTHORS index e1966c5af5..ecdb98f91e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -252,6 +252,7 @@ answer newbie questions, and generally made Django that much better: Armin Ronacher Brian Rosner Oliver Rutherfurd + ryankanno Ivan Sagalaev (Maniac) Vinay Sajip David Schein diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py index dcb58e85d8..2e4fb92cda 100644 --- a/django/contrib/formtools/preview.py +++ b/django/contrib/formtools/preview.py @@ -1,47 +1,5 @@ """ Formtools Preview application. - -This is an abstraction of the following workflow: - - "Display an HTML form, force a preview, then do something with the submission." - -Given a django.newforms.Form object that you define, this takes care of the -following: - - * Displays the form as HTML on a Web page. - * Validates the form data once it's submitted via POST. - * If it's valid, displays a preview page. - * If it's not valid, redisplays the form with error messages. - * At the preview page, if the preview confirmation button is pressed, calls - a hook that you define -- a done() method. - -The framework enforces the required preview by passing a shared-secret hash to -the preview page. If somebody tweaks the form parameters on the preview page, -the form submission will fail the hash comparison test. - -Usage -===== - -Subclass FormPreview and define a done() method: - - def done(self, request, cleaned_data): - # ... - -This method takes an HttpRequest object and a dictionary of the form data after -it has been validated and cleaned. It should return an HttpResponseRedirect. - -Then, just instantiate your FormPreview subclass by passing it a Form class, -and pass that to your URLconf, like so: - - (r'^post/$', MyFormPreview(MyForm)), - -The FormPreview class has a few other hooks. See the docstrings in the source -code below. - -The framework also uses two templates: 'formtools/preview.html' and -'formtools/form.html'. You can override these by setting 'preview_template' and -'form_template' attributes on your FormPreview subclass. See -django/contrib/formtools/templates for the default templates. """ from django.conf import settings diff --git a/docs/add_ons.txt b/docs/add_ons.txt index a1d78b8685..00c6e0dcf4 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -70,8 +70,9 @@ An abstraction of the following workflow: "Display an HTML form, force a preview, then do something with the submission." -Full documentation for this feature does not yet exist, but you can read the -code and docstrings in ``django/contrib/formtools/preview.py`` for a start. +See the `form preview documentation`_. + +.. _form preview documentation: ../form_preview/ humanize ======== diff --git a/docs/form_preview.txt b/docs/form_preview.txt new file mode 100644 index 0000000000..4be7b07a74 --- /dev/null +++ b/docs/form_preview.txt @@ -0,0 +1,97 @@ +============ +Form preview +============ + +Django comes with an optional "form preview" application that helps automate +the following workflow: + +"Display an HTML form, force a preview, then do something with the submission." + +To force a preview of a form submission, all you have to do is write a short +Python class. + +Overview +========= + +Given a ``django.newforms.Form`` subclass that you define, this application +takes care of the following workflow: + + 1. Displays the form as HTML on a Web page. + 2. Validates the form data when it's submitted via POST. + a. If it's valid, displays a preview page. + b. If it's not valid, redisplays the form with error messages. + 3. When the "confirmation" form is submitted from the preview page, calls + a hook that you define -- a ``done()`` method that gets passed the valid + data. + +The framework enforces the required preview by passing a shared-secret hash to +the preview page via hidden form fields. If somebody tweaks the form parameters +on the preview page, the form submission will fail the hash-comparison test. + +How to use ``FormPreview`` +========================== + + 1. Point Django at the default FormPreview templates. There are two ways to + do this: + + * Add ``'django.contrib.formtools'`` to your ``INSTALLED_APPS`` + setting. This will work if your ``TEMPLATE_LOADERS`` setting includes + the ``app_directories`` template loader (which is the case by + default). See the `template loader docs`_ for more. + + * Otherwise, determine the full filesystem path to the + ``django/contrib/formtools/templates`` directory, and add that + directory to your ``TEMPLATE_DIRS`` setting. + + 2. Create a ``FormPreview`` subclass that overrides the ``done()`` method:: + + from django.contrib.formtools import FormPreview + from myapp.models import SomeModel + + class SomeModelFormPreview(FormPreview): + + def done(self, request, cleaned_data): + # Do something with the cleaned_data, then redirect + # to a "success" page. + return HttpResponseRedirect('/form/success') + + This method takes an ``HttpRequest`` object and a dictionary of the form + data after it has been validated and cleaned. It should return an + ``HttpResponseRedirect`` that is the end result of the form being + submitted. + + 3. Change your URLconf to point to an instance of your ``FormPreview`` + subclass:: + + from myapp.preview import SomeModelFormPreview + from myapp.models import SomeModel + from django import newforms as forms + + ...and add the following line to the appropriate model in your URLconf:: + + (r'^post/$', SomeModelFormPreview(forms.models.form_for_model(SomeModel))), + + Or, if you already have a Form class defined for the model:: + + (r'^post/$', SomeModelFormPreview(SomeModelForm)), + + 4. Run the Django server and visit ``/post/`` in your browser. + +.. _template loader docs: ../templates_python/#loader-types + +``FormPreview`` classes +======================= + +A ``FormPreview`` class is a simple Python class that represents the preview +workflow. ``FormPreview`` classes must subclass +``django.contrib.formtools.preview.FormPreview`` and override the ``done()`` +method. They can live anywhere in your codebase. + +``FormPreview`` templates +========================= + +By default, the form is rendered via the template ``formtools/form.html``, and +the preview page is rendered via the template ``formtools.preview.html``. +These values can be overridden for a particular form preview by setting +``preview_template`` and ``form_template`` attributes on the FormPreview +subclass. See ``django/contrib/formtools/templates`` for the default templates.