Sometimes you'd need to show a purely informational page as part of a FormWizard. As far as I could see, there are two solutions to the problem:
- If the info is something like a summary, you have it available in the "success" page (the one after the wizard is finished)
- Alternatively, you can make it a page in the wizard.
The more challenging and versatile variant is the second one (versatile because it gives you the possibility to go back to a previous step to correct stuff).
My Solution
My solution is somewhat of an abuse of the FormWizard functionality (but perfectly legal, I assure you).
A Form
First, each step must have a form. So, you need to assign a form class to the "empty form" step. I did it by creating an empty form:
class EmptyForm(forms.Form):
"""
A form to show an information panel.
"""
pass
This form needs to be added to your list of steps:
class ConfigurationWizard(SessionWizardView):
"""
Configuration wizard
"""
template_name = "configuration/base.html"
form_list = [
(STEP_ONE, ToolForm), #
(STEP_UID, IDForm), #
(STEP_CONFIG, EmptyForm) # <- This is the info panel
]
Build Data
Once we've built the list of steps, and we have our panel, we need to build some data we can use. To this effect, we use the standard django view approach via context variables. The FormWizard provides us with a context method which we overload:
def get_context_data(self, form, **kwargs):
"""
Get custom context data for the config step
"""
context = super(ConfigurationWizard, self).get_context_data(
form=form, **kwargs
)
# If we have the CONFIG step, then build the context data from
# the previous ones. This way, we can have a variable render-able
# directly in a template.
#
if self.steps.current == STEP_CONFIG:
tool = "%s" % self.get_cleaned_data_for_step(STEP_TOOL)[
'tool'].get_slug()
key = "%s" % self.get_cleaned_data_for_step(STEP_UID)['id']
context.update({
'tool': tool,
'key': key
})
return context
Using the Data
Cool. Now we have the data available. To use it, we only need to load a custom template. Fortunately, FormWizard allows loading different templates for different steps. To do this, I added a dict of custom templates:
class ConfigurationWizard(SessionWizardView):
# ...
# ...
# ...
templates = {
STEP_CONFIG: "config/form-config.html"
}
and overloaded the get_template_names() method:
def get_template_names(self):
"""
Allow retrieving custom templates for different steps.
:return: an array with the relevant template for the current step
"""
try:
t_names = [ConfigurationWizard.templates[self.steps.current]]
return t_names
except KeyError, e:
default_template = super(ConfigurationWizard,
self).get_template_names()
return default_template
My template looks like this:
{% extends "config/base.html" %}
{% load staticfiles i18n %}
{% load url from future %}
{% block content %}
<h3>Configuration</h3>
<p>Your configuration data is:</p>
{% spaceless %}
<pre>
<code class="json">{
"tool": "{{ tool }}",
"key": "{{ key }}",
}</code>
</pre>
{% endspaceless %}
<p>Copy it or</p>
<a class="btn btn-default"
href="{% url 'download_config' %}?key={{ key }}&tool={{ tool }}">
Download <strong>your configuration file</strong>
</a>
{% endblock %}
Summary
To make this panel work you need to:
- Create an empty form and add it to a FormWizard step
- Build a template context for the relevant step
- Build a custom template and load it
HTH,
Member discussion: