Registry / web-framework / django-formtools

django-formtools

JSON →
library2.7pypypi✓ verified 30d ago

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.

pip install django-formtools
INSTALL
IMPORT
SIG · DJANGO-FORMTOOLS
D
django-formtools
web-frameworkpythonv2.7
Install
3.6s avg
Import
810ms
Disk
67MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v2.7 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.866s · 67.7MB
glibc
py 3.10–3.95 runs
installs and imports cleanly · install 3.6s · import 0.754s · 68MB
67MB installed
● package 67MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

SessionWizardView
✓ from formtools.wizard.views import SessionWizardView
✗ from django.contrib.formtools.wizard.views import WizardView
The `formtools` package was moved out of `django.contrib` in Django 1.8. Old import paths are no longer valid.
CookieWizardView
✓ from formtools.wizard.views import CookieWizardView
✗ from django.contrib.formtools.wizard.views import CookieWizardView
The `formtools` package was moved out of `django.contrib` in Django 1.8. Old import paths are no longer valid.
NamedUrlWizardView
✓ from formtools.wizard.views import NamedUrlWizardView
✗ from django.contrib.formtools.wizard.views import NamedUrlWizardView
The `formtools` package was moved out of `django.contrib` in Django 1.8. Old import paths are no longer valid.
FormPreview
✓ from formtools.preview import FormPreview
✗ from django.contrib.formtools.preview import FormPreview
The `formtools` package was moved out of `django.contrib` in Django 1.8. Old import paths are no longer valid.

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>
Debug
Known issues
breakingThe `django-formtools` package was moved from `django.contrib.formtools` to its own standalone package `formtools` in Django 1.8. All import paths changed accordingly.
fix
Update import statements from `from django.contrib.formtools...` to `from formtools...`.
affects: Django 1.8 and higher, django-formtools 1.0 and higher
gotchaYou must add `'formtools'` to your `INSTALLED_APPS` setting in `settings.py` for its templates (like `wizard_form.html`) and internationalization (translations) to be discovered and used correctly.
fix
Add `'formtools'` to your `INSTALLED_APPS` list.
affects: All versions
gotcha`FormPreview` does not support file uploads. If your forms contain `FileField`s, you should implement the preview logic manually or use `WizardView` which supports file handling.
fix
Avoid using `FormPreview` with forms that include `FileField`. For wizards, refer to the 'Handling files' section in the `WizardView` documentation.
affects: All versions
breakingIn `django-formtools` 2.4.1, support for Python 3.6 and Django versions older than 3.2 was dropped.
fix
Ensure your project uses Python >= 3.7 (preferably >= 3.8) and Django >= 3.2.
affects: django-formtools 2.4.1 and higher
gotchaBy default, `SessionWizardView` and `CookieWizardView` manage state across steps, but they do not inherently provide mechanisms to restore a user's progress if they leave the site and return later. Additionally, `CookieWizardView` now restarts the wizard from the first step if an invalid cookie is detected, instead of raising a `SuspiciousOperation` error.
fix
For persistent session data across user visits, override the `get()` method in your `SessionWizardView` subclass to load saved data. Be aware of the `CookieWizardView`'s new behavior regarding invalid cookies.
affects: `SessionWizardView` all versions; `CookieWizardView` 2.4 and higher for new cookie behavior.
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'formtools'
The `formtools` application was moved from `django.contrib.formtools` to a standalone package `django-formtools` in Django 1.8. This error occurs if you are using an older import path or have not installed the standalone `django-formtools` package.
fix
First, ensure `django-formtools` is installed: `pip install django-formtools`. Then, update all import statements from `from django.contrib.formtools...` to `from formtools...` in your code.
SuspiciousOperation: ManagementForm data is missing or has been tampered with.
This error typically occurs in a `SessionWizardView` if the hidden `{{ wizard.management_form }}` field is missing from one of your wizard's templates, or if the form's management data is somehow altered or corrupted between steps.
fix
Ensure that `{{ wizard.management_form }}` is present within the `<form>` tags of all your wizard step templates. Also, avoid manually manipulating hidden fields that `django-formtools` uses to manage state.
Django formtools 'done' method is not getting called on form submission
The `done()` method in a `SessionWizardView` subclass is only executed after the *final* step of the multi-step form wizard has been successfully submitted and all forms have passed validation. If an intermediate step's form validation fails, or if the wizard's state is somehow reset, the `done()` method will not be reached.
fix
Verify that all forms in the wizard (from the first to the last step) are validating correctly. If forms are failing validation, the wizard will re-render the current step with errors instead of proceeding to `done()`. Use the `process_step()` method if you need to perform actions after each successful step.
TemplateDoesNotExist at /my-wizard-url/ formtools/wizard/wizard_form.html
Django cannot locate the default templates provided by `django-formtools` for rendering the wizard or preview pages. This often happens if `'formtools'` is not added to your `INSTALLED_APPS` setting in `settings.py`, or if your template loaders are not configured to discover app templates.
fix
Add `'formtools'` to your `INSTALLED_APPS` list in your `settings.py` file. Ensure your `TEMPLATES` setting includes the `django.template.loaders.app_directories.Loader` or explicitly lists the `formtools/templates` directory in the `DIRS` option.
Upgrade
Version history
2.7latest on PyPI · released Jul 9, 2026
Audit
Dependencies
DjangorequiredCore framework dependency, requires Django>=4.2 for recent versions.
Agent activity
11 hits · last 30 days
node
10
Resources
django-formtools — pip install django-formtools · libregistry