Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SessionWizardView state only saved on final form, done() not executed

I have several forms I have added to a wizard, but form state is only maintained for the final step, and done() is not executed.

I have created the following, heavily based off the examples on django's documentation, to try get to the bottom of this. It seems the final step is the only one that saves the state when moving amongst the steps.

class OneForm( Form ):
    field_one = forms.CharField(label='1', max_length=100)
    field_two = forms.CharField(label='2', max_length=100)
    field_three = forms.CharField(label='3', max_length=100)
class TwoForm( Form ):
    field_one = forms.CharField(label='4', max_length=100)
    field_two = forms.CharField(label='5', max_length=100)
    field_three = forms.CharField(label='6', max_length=100)

TEST_WIZARD_FORMS = [
    ("one", OneForm),
    ("two", TwoForm),
]
TEST_TEMPLATES = {
    'one': 'tour/one.html',
    'two': 'tour/two.html',
}
class TestWizardView( SessionWizardView ):
    form_list = TEST_WIZARD_FORMS
    def done(self, form_list, **kwargs):
        print('done executed')
        return reverse('home')
    def get_template_names(self):
        return [TEST_TEMPLATES[self.steps.current]]

and this for templates (both one.html and two.html are identical)

<html>
<body>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
    {{ wizard.form.management_form }}
    {{ wizard.form.non_field_errors }}
    {{ wizard.form.errors }}
    {% for form in wizard.form.forms %}
        {{ form }}
    {% endfor %}
{% else %}
    {{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button>
{% endif %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.next }}">"next step"</button>
<input type="submit" value="submit"/>
</form>
</body>
</html>

If I enter data on step 1, proceed to step 2 and enter data, then return to step 1, the first step has no data saved and no form errors displayed. When I hit next to return to step 2, step 2's data is still present. Intentionally putting invalid data on step 1 has shown me that it does not validate the form either, as the wizard continues to step 2 without displaying errors.

When I submit the form, done() does not execute. This makes sense if only the last step is actually successful, but seeing no errors on step 1 has me baffled.

Why is form data not maintained except on the final form? Why is the final step the only one that actually validates form data? Why is done not executed?

Update: It appears the form validation is happening afterall, and I do see it succeeding via printing relevant information in the post function, but done() still does not seem to get executed.

Thank you.

like image 394
wilbbe01 Avatar asked Nov 10 '15 04:11

wilbbe01


1 Answers

Step 1 in the documentation found here is the answer. It states the following.

The user visits the first page of the wizard, fills in the form and submits it.

The key here is the "submit." No form validation or state is saved unless the form is submitted. Using the wizard_goto_step for next/previous/jump does not submit the form, does not validate the form, and does not save the form in the session/cookie (depending which you choose).

It is obvious now, but I still think this is misleading to potential end users of the form wizard. It is easy enough for me to replace the wizard_goto_step with an actual submit when going to the next step, but when users enter some data in a form, and subsequently choose to revisit another step, all of their data on that step is lost.

It feels like form data should be saved even when incomplete. My intention is to save this data manually using the storage.set_step_data() function, as all form steps are re-validated at the final processing anyway. Even if a user fills out incorrect data on a step they will still be redirected to the step with missing data at the end. This feels like better behavior than blindly wiping the user's data on a step when they visit a previous step.

like image 165
wilbbe01 Avatar answered Sep 27 '22 18:09

wilbbe01