Search code examples
pythondjangodjango-formwizard

custom template not working in django formtools


I have been trying to add a multi page form in my Django application using the formtools wizard. I need to setup custom forms for each step. There are 2 steps in total. Here is the code that I have:

views.py

TEMPLATES = {"initial": "my_app/form_initial.html",
         "final": "my_app/form_last.html"}


class ModelCreateView(SessionWizardView):
    model = MyModel
    template_name = "my_app/model_form.html"
    file_storage =      
    FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'custom'))

    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

my_app/model_form.html

{% extends "my_app/base.html" %}

{% block extra_css %}
{{ wizard.form.media }}
{% endblock %}

{% block content %}
<form action="" method="post">
{% csrf_token %}
    {{ wizard.management_form }}
    <h1>{{ wizard }}</h1>
    {% if wizard.form.forms %}
        <h1>{{ wizard.form.forms }}</h1>
        {{ wizard.form.management_form }}
        {% for form in wizard.form.forms %}
            {{ form }}
        {% endfor %}
    {% else %}
        {{ wizard.form }}
    {% endif %}
    <input type="submit" value="submit"/>
</form>
{% endblock content %}

my_app/form_initial.html

 <-- custom form template for step 1 -->

my_app/form_last.html

 <-- custom form template for step 2 -->

if I understand it correctly, the custom form templates will replace the

{{ form }}

tag in the base template being called(my_app/model_form.html).

My problem here is that, with the current code, the my_app/form_initial.html is being called directly.

Also if I try to just include

{{ wizard.management_form }}

in my_app/form_initial.html and enclose the necessary form elements, on submit, it just reloads the current page rather than taking me to my_app/form_last.html

Please let me know what am I doing wrong here.

UPDATE: I fixed the issue with custom template by properly extending the base form template. But now when I submit on the first step, the same step page reloads rather than going to the next step. Please let me know how do I debug this?

UPDATE 2: I tried debugging more and found this, my fields are not getting validated even though the post request contains the fields, the form.is_valid() returns false. The form.errors says that all the fields are missing


Solution

  • There were 2 problems in the method that I had implemented the templates.

    1. I had assumed that the custom step form templates would be substituted in their own once a base template is defined in the view. The correct method to do this is define the base template template and extend it in the custom step template.

    eg:

    base_form_template.html

    {% block content %}
    <form style="height:inherit;" action="" method="post">
    {% csrf_token %}
        {{ wizard.management_form }}
        {{ wizard.form.errors}}
        {{ wizard.form.non_field_errors}}
        {% block custom_form %}
        {% endblock %}
    </form>
    {% endblock content %}
    

    step1.html

    {% extends "my_app/base_form_template.html" %}
    
    <-- custom form template code goes here -->
    

    step2.html

    {% extends "my_app/base_form_template.html" %}
    
    <-- custom form template code goes here -->
    
    1. In my custom form template, the name attribute of the input fields need to be set to wizard.form.<model_attribute>.html_name. This was difficult to find. I had initially just set it wizard.form.<model_attribute> and wondered why it didn't work. Did some more digging and found this. The html_name is different as its of the format <step_name>_<field_name>. Looking at it now it does make sense to have names like this.