django-formtools

2.5.1 · active · verified Sat Apr 11

django-formtools is a collection of high-level abstractions designed to simplify complex form use cases in Django applications. It primarily offers utilities for form previews and multi-step form wizards. Originally a part of Django's core (`django.contrib.formtools`), it was extracted into a standalone package in Django 1.8 to facilitate independent maintenance and trim the framework's core. The library is actively maintained by the Jazzband community, with releases typically following new Django versions to ensure compatibility.

Warnings

Install

Imports

Quickstart

To use `django-formtools`, define your form classes, then create a `WizardView` subclass (e.g., `SessionWizardView`) that specifies the forms and implements a `done` method to handle the final submission. The view needs to be hooked into your `urls.py`. Remember to add `'formtools'` to your `INSTALLED_APPS` in `settings.py` for templates and translations to work correctly.

import os
from django import forms
from django.shortcuts import render
from django.urls import path
from formtools.wizard.views import SessionWizardView

# forms.py (example)
class ContactForm1(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()

class ContactForm2(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)

# views.py (example)
FORMS = [("step1", ContactForm1), ("step2", ContactForm2)]
TEMPLATES = {"step1": "wizard_form.html", "step2": "wizard_form.html"}

class ContactWizard(SessionWizardView):
    def get_template_names(self):
        # Dynamically selects template based on current step
        return [TEMPLATES[self.steps.current]]

    def done(self, form_list, **kwargs):
        # Process the cleaned data from all forms after the wizard is complete
        cleaned_data = [form.cleaned_data for form in form_list]
        return render(self.request, 'done.html', {'form_data': cleaned_data})

# urls.py (example)
# urlpatterns = [
#     path('contact/', ContactWizard.as_view(FORMS)),
# ]

# To make this runnable as a standalone quickstart for illustration (requires a Django project setup)
# In a real Django project, you'd add 'formtools' to INSTALLED_APPS and set up templates.
# For testing, you can manually run the view logic (not a full server setup).

# Example of what your templates/wizard_form.html might look like:
# <h1>Step {{ wizard.steps.current }} of {{ wizard.steps.total }}</h1>
# <form action="" method="post">{% csrf_token %}
#     {{ wizard.management_form }}
#     {{ wizard.form.as_p }}
#     <input type="submit" value="{% if wizard.steps.next %}Next{% else %}Submit{% endif %}">
# </form>

# Example of what your templates/done.html might look like:
# <h1>Wizard Complete!</h1>
# <p>Form Data:</p>
# <ul>
#     {% for form_data in form_data %}
#         <li>{{ form_data }}</li>
#     {% endfor %}
# </ul>

view raw JSON →