diff options
Diffstat (limited to 'parts/django/docs/ref/contrib/formtools')
-rw-r--r-- | parts/django/docs/ref/contrib/formtools/form-preview.txt | 121 | ||||
-rw-r--r-- | parts/django/docs/ref/contrib/formtools/form-wizard.txt | 312 | ||||
-rw-r--r-- | parts/django/docs/ref/contrib/formtools/index.txt | 10 |
3 files changed, 0 insertions, 443 deletions
diff --git a/parts/django/docs/ref/contrib/formtools/form-preview.txt b/parts/django/docs/ref/contrib/formtools/form-preview.txt deleted file mode 100644 index a2cbea7..0000000 --- a/parts/django/docs/ref/contrib/formtools/form-preview.txt +++ /dev/null @@ -1,121 +0,0 @@ -============ -Form preview -============ - -.. module:: django.contrib.formtools - :synopsis: Displays an HTML form, forces a preview, then does something - with the submission. - -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 :class:`django.forms.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 - :meth:`~django.contrib.formtools.FormPreview.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 - :setting:`INSTALLED_APPS` setting. This will work if your - :setting:`TEMPLATE_LOADERS` setting includes the - ``app_directories`` template loader (which is the case by - default). See the :ref:`template loader docs <template-loaders>` - for more. - - * Otherwise, determine the full filesystem path to the - :file:`django/contrib/formtools/templates` directory, and add that - directory to your :setting:`TEMPLATE_DIRS` setting. - - 2. Create a :class:`~django.contrib.formtools.FormPreview` subclass that - overrides the :meth:`~django.contrib.formtools.FormPreview.done()` - method:: - - from django.contrib.formtools.preview 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 :class:`~django.http.HttpRequest` object and a - dictionary of the form data after it has been validated and cleaned. - It should return an :class:`~django.http.HttpResponseRedirect` that - is the end result of the form being submitted. - - 3. Change your URLconf to point to an instance of your - :class:`~django.contrib.formtools.FormPreview` subclass:: - - from myapp.preview import SomeModelFormPreview - from myapp.forms import SomeModelForm - from django import forms - - ...and add the following line to the appropriate model in your URLconf:: - - (r'^post/$', SomeModelFormPreview(SomeModelForm)), - - where ``SomeModelForm`` is a Form or ModelForm class for the model. - - 4. Run the Django server and visit :file:`/post/` in your browser. - -``FormPreview`` classes -======================= - -.. class:: FormPreview - -A :class:`~django.contrib.formtools.FormPreview` class is a simple Python class -that represents the preview workflow. -:class:`~django.contrib.formtools.FormPreview` classes must subclass -``django.contrib.formtools.preview.FormPreview`` and override the -:meth:`~django.contrib.formtools.FormPreview.done()` method. They can live -anywhere in your codebase. - -``FormPreview`` templates -========================= - -By default, the form is rendered via the template :file:`formtools/form.html`, -and the preview page is rendered via the template :file:`formtools/preview.html`. -These values can be overridden for a particular form preview by setting -:attr:`~django.contrib.formtools.FormPreview.preview_template` and -:attr:`~django.contrib.formtools.FormPreview.form_template` attributes on the -FormPreview subclass. See :file:`django/contrib/formtools/templates` for the -default templates. - -Advanced ``FormPreview`` methods -================================ - -.. versionadded:: 1.2 - -.. method:: FormPreview.process_preview - - Given a validated form, performs any extra processing before displaying the - preview page, and saves any extra data in context. - - By default, this method is empty. It is called after the form is validated, - but before the context is modified with hash information and rendered. diff --git a/parts/django/docs/ref/contrib/formtools/form-wizard.txt b/parts/django/docs/ref/contrib/formtools/form-wizard.txt deleted file mode 100644 index 390d575..0000000 --- a/parts/django/docs/ref/contrib/formtools/form-wizard.txt +++ /dev/null @@ -1,312 +0,0 @@ -=========== -Form wizard -=========== - -.. module:: django.contrib.formtools.wizard - :synopsis: Splits forms across multiple Web pages. - -.. versionadded:: 1.0 - -Django comes with an optional "form wizard" application that splits -:doc:`forms </topics/forms/index>` across multiple Web pages. It maintains -state in hashed HTML :samp:`<input type="hidden">` fields, and the data isn't -processed server-side until the final form is submitted. - -You might want to use this if you have a lengthy form that would be too -unwieldy for display on a single page. The first page might ask the user for -core information, the second page might ask for less important information, -etc. - -The term "wizard," in this context, is `explained on Wikipedia`_. - -.. _explained on Wikipedia: http://en.wikipedia.org/wiki/Wizard_%28software%29 -.. _forms: ../forms/ - -How it works -============ - -Here's the basic workflow for how a user would use a wizard: - - 1. The user visits the first page of the wizard, fills in the form and - submits it. - 2. The server validates the data. If it's invalid, the form is displayed - again, with error messages. If it's valid, the server calculates a - secure hash of the data and presents the user with the next form, - saving the validated data and hash in :samp:`<input type="hidden">` - fields. - 3. Step 1 and 2 repeat, for every subsequent form in the wizard. - 4. Once the user has submitted all the forms and all the data has been - validated, the wizard processes the data -- saving it to the database, - sending an e-mail, or whatever the application needs to do. - -Usage -===== - -This application handles as much machinery for you as possible. Generally, you -just have to do these things: - - 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:`FormWizard` class. - -Defining ``Form`` classes -========================= - -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 :doc:`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 - - class ContactForm1(forms.Form): - subject = forms.CharField(max_length=100) - sender = forms.EmailField() - - class ContactForm2(forms.Form): - 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.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` 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:`~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 :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:: - - from django.shortcuts import render_to_response - from django.contrib.formtools.wizard import FormWizard - - class ContactWizard(FormWizard): - def done(self, request, form_list): - return render_to_response('done.html', { - 'form_data': [form.cleaned_data for form in form_list], - }) - -Note that this method will be called via ``POST``, so it really ought to be a -good Web citizen and redirect after processing the data. Here's another -example:: - - from django.http import HttpResponseRedirect - from django.contrib.formtools.wizard import FormWizard - - class ContactWizard(FormWizard): - def done(self, request, form_list): - do_something_with_the_form_data(form_list) - return HttpResponseRedirect('/page-to-redirect-to-when-done/') - -See the section `Advanced FormWizard methods`_ below to learn about more -: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:`~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: - - * ``step_field`` -- The name of the hidden field containing the step. - * ``step0`` -- The current step (zero-based). - * ``step`` -- The current step (one-based). - * ``step_count`` -- The total number of steps. - * ``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 :tfilter:`safe` template filter, - to prevent auto-escaping, because it's raw HTML. - -You can supply extra context to this template in two ways: - - * Set the :attr:`~FormWizard.extra_context` attribute on your - :class:`FormWizard` subclass to a dictionary. - - * 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: - -.. code-block:: html+django - - {% extends "base.html" %} - - {% block content %} - <p>Step {{ step }} of {{ step_count }}</p> - <form action="." method="post">{% csrf_token %} - <table> - {{ form }} - </table> - <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> - {{ previous_fields|safe }} - <input type="submit"> - </form> - {% endblock %} - -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, we need to specify which forms to use in the wizard, and then -deploy the new :class:`FormWizard` object a URL in ``urls.py``. The -wizard takes a list of your :class:`~django.forms.Form` objects as -arguments when you instantiate the Wizard:: - - from django.conf.urls.defaults import * - from testapp.forms import ContactForm1, ContactForm2, ContactWizard - - urlpatterns = patterns('', - (r'^contact/$', ContactWizard([ContactForm1, ContactForm2])), - ) - -Advanced ``FormWizard`` methods -=============================== - -.. class:: FormWizard - - 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``.) - -.. method:: FormWizard.prefix_for_step - - 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:: - - def prefix_for_step(self, step): - return str(step) - -.. method:: FormWizard.render_hash_failure - - Renders a template if the hash check fails. It's rare that you'd need to - override this. - - Default implementation:: - - 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.'}) - -.. method:: FormWizard.security_hash - - 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. - - Example:: - - def security_hash(self, request, form): - return my_hash_function(request, form) - -.. 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. - - By default, this does nothing. - - Example:: - - def parse_params(self, request, *args, **kwargs): - self.my_state = args[0] - -.. method:: FormWizard.get_template - - Returns the name of the template that should be used for the given step. - - By default, this returns :file:`'forms/wizard.html'`, regardless of step. - - Example:: - - 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. - 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'] - -.. 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. - - The template will be rendered with the context documented in the - "Creating templates for the forms" section above. - -.. method:: FormWizard.process_step - - Hook for modifying the wizard's internal state, given a fully validated - :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. - - Note that this method is called every time a page is rendered for *all* - submitted steps. - - The function signature:: - - def process_step(self, request, form, step): - # ... diff --git a/parts/django/docs/ref/contrib/formtools/index.txt b/parts/django/docs/ref/contrib/formtools/index.txt deleted file mode 100644 index f364706..0000000 --- a/parts/django/docs/ref/contrib/formtools/index.txt +++ /dev/null @@ -1,10 +0,0 @@ -django.contrib.formtools -======================== - -A set of high-level abstractions for Django forms (:mod:`django.forms`). - -.. toctree:: - :maxdepth: 1 - - form-preview - form-wizard |