Django formtools wizard produces blank page (No error returned)

376 views
Skip to first unread message

Martin Torre Castro

unread,
Jan 30, 2016, 5:18:07 AM1/30/16
to Django users
I'm trying to use the formwizard in formtools package with no success (I was able to do it when the package was inside Django in earlier versions). 

The only response I got is:

    [23/Jan/2016 11:06:50]"GET /registration/wizard HTTP/1.1" 200 13729

and a blank page. No errors in browser or Eclipse console.

There's no way of googling without errors. Please help.

Thanks in advance

(If you guys find more comfortable stackoverflow, you can go to http://stackoverflow.com/q/34962499/1241715)


What did I do?

Firstly, I installed the formtools package with pip:

    django-formtools==1.0
    Django==1.8.3


Following the instructions of the official docs:

  1. Define form classes

    registration/forms.py

    class StepForm1(forms.Form):
        first_field = forms.CharField(max_length=100)
        second_field = forms.CharField()

    class StepForm2(forms.Form):
        message = forms.CharField(widget=forms.Textarea)

  2. Create WizardView

    registration/views.py

    TEST_TEMPLATES = {"test_step_1": "registration/test_step1.html", "test_step_2": "registration/test_step2.html", }

    from formtools.wizard.views import SessionWizardView

    class WizardTest(SessionWizardView):
        template_name = 'registration/test_wizard.html'

        # Return templates for each step
        def get_templates_name(self):
            return [TEST_TEMPLATES[self.steps.current]]

        # Method called when all is done
        def done(self, form_list, **kwargs):
            # return HttpResponseRedirect('/url-to-redirect-to/') 

            # We return the final template with the info
            return render_to_response('test_done.html', {
                                                                                   'form_data':[form.cleaned_data for form in form_list],
                                                                                   })
        # THESE METHODS BELOW ARE NOT NEEDED, BUT COMMENTED FOR FUTURE USE

        # Not strictly needed. Returns data for a step
        # or None if form is not valid

        # def get_cleaned_data_for_step(self, step):
            #return None

        # Form data postprocessing in a concrete wizard step
        # def process_step(self, form):
            #return self.get_form_step_data(form)

        # Handles value from a step before storing them into wizard
        # def get_form_step_data(self, form):
            #return form.data

  3. Create the templates

    registration/test_step1.html

    <h1>Two fields form</h1>
    <input id="first_field" name="first_field">
    <input id="second_field" name="second_field">

    registration/test_step2.html

    <h1>Message form</h1>
    <input id="message" name="message">

    registration/test_wizard.html

    {% extends "person/alumnos.html" %}
    {% load i18n %}

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

    {% block content %}
        <p>{% trans "Step {{wizard.steps.step1}} of {{wizard.steps.count}}" %}</p>
        <form action="" method="post">
            {% csrf_token %}

            {{ wizard.management_form }}
            {% if wizard.form.forms  %}
                {{ wizard.form.management_form }}
                {% for form in wizard.form.forms %}
                    {{form}}
                {% endfor %}
            {% else %}
                {{ wizard.form }}
            {% endif %}

            {% if wizard.steps.prev %}
                <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "Beginning" %}</button>
                <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "Previous step" %}</button>
            {% endif %}

            <input type="submit" value="submit"/>
        </form>
    {% endblock %}

  4. Add 'formtools' to my INSTALLED_APPS

    settings.py

    DJANGO_APPS = (
        # Default Django apps:
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        'django.contrib.staticfiles',
       
        'formtools',                 # <===== HERE
       
        # Useful template tags:
        # 'django.contrib.humanize',
        # Admin panel and documentation:
        'django.contrib.admin',
        # 'django.contrib.admindocs',
    )

    # Apps specific for this project go here.
    LOCAL_APPS = (
        'person',
        'registration',
        'teaching',
        'utils',
    )

    # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
    INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS

  5. Point my URLconf at your WizardView as_view() method.

    registration/urls.py

    from registration.forms import StepForm1, StepForm2

    TEST_FORMS = [("test_step_1", StepForm1), ("test_step_2", StepForm2), ]

    from registration.views import WizardTest

    # I tried in two ways, none of them worked

    urlpatterns = patterns('',
        url(r'^wizard$', WizardTest.as_view(TEST_FORMS), name='wizard_test'),
        url(r'^wizard2$', views.wizard, name='wizard_test'),
    )

    For the second way...

    registration/views.py

    def wizard(request):
        return WizardTest.as_view(TEST_FORMS)(request)


James Schneider

unread,
Jan 30, 2016, 7:56:11 AM1/30/16
to django...@googlegroups.com

Your view is returning a 200 code, so it thinks it is finishing correctly with no errors, probably the reason you don't see any errors.

At what point do you get a blank page? Initial load? Final step? Does the template in your done() step exist? Have you installed the Django-debug-toolbar to examine the context of your blank page?

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/333f094e-3b3f-4235-b3df-1b5d76c3004f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Martín Torre Castro

unread,
Jan 30, 2016, 11:24:29 AM1/30/16
to django...@googlegroups.com

I can't see the initial load, which is the same as saying that the first step does not load.

You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/mAi_fB_MTwo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Martín Torre Castro

unread,
Jan 31, 2016, 5:17:53 PM1/31/16
to django...@googlegroups.com
Hi, James,

I'm trying with the django-debug-toolbar. I can't see anything because the message "500: INTERNAL SERVER ERROR" appears. I tried in all the options and keeps showing this 500 code message.

But it comes to my attention that, for example, the tooltip for "templates" shows "3 templates rendered". Anyway, I can't get the headers, the request or anything using the django-debug-toolbar. :-(

I will keep on with testing this.

James Schneider

unread,
Feb 1, 2016, 6:07:09 PM2/1/16
to django...@googlegroups.com
On Sun, Jan 31, 2016 at 2:16 PM, Martín Torre Castro <martin.to...@gmail.com> wrote:
Hi, James,

I'm trying with the django-debug-toolbar. I can't see anything because the message "500: INTERNAL SERVER ERROR" appears. I tried in all the options and keeps showing this 500 code message.

But it comes to my attention that, for example, the tooltip for "templates" shows "3 templates rendered". Anyway, I can't get the headers, the request or anything using the django-debug-toolbar. :-(

I will keep on with testing this.

Well, a 5XX error indicates an internal error. If you have DEBUG=True in your settings, Django should show you a traceback of what error it encountered. If it doesn't, you have a deeper problem with the web server itself, possibly with loading Django. You mentioned in your logs that you were receiving 2XX codes, which is contradictory.

-James
 

Martín Torre Castro

unread,
Feb 2, 2016, 3:27:54 AM2/2/16
to django...@googlegroups.com
I have DEBUG = True in my settings. When making the request the 200 http code appears. The 500 "Internal server error" code only appears when trying to obtain info through the django-debug-toolbar

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/mAi_fB_MTwo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

James Schneider

unread,
Feb 2, 2016, 4:07:54 AM2/2/16
to django...@googlegroups.com
On Tue, Feb 2, 2016 at 12:26 AM, Martín Torre Castro <martin.to...@gmail.com> wrote:
I have DEBUG = True in my settings. When making the request the 200 http code appears. The 500 "Internal server error" code only appears when trying to obtain info through the django-debug-toolbar


In that case you should be seeing something in your web server logs regarding the internal server error. I'd be quite surprised if the debug toolbar was the cause of the error. It must be something being set somewhere that it isn't expecting.


I went back through your code posting, and I was curious about something:

registration/test_step1.html

<h1>Two fields form</h1>
<input id="first_field" name="first_field">
<input id="second_field" name="second_field">

registration/test_step2.html

<h1>Message form</h1>
<input id="message" name="message">

Are these your actual templates? I originally made an assumption that you had intentionally omitted the {% block %} and {% extends %} tags, but now I'm wondering if these are the actual templates and what you are receiving when you see a blank page is actually just the raw HTML that you posted above (check the source of the blank page)?

Just a thought. 

-James

Martín Torre Castro

unread,
Feb 2, 2016, 4:18:00 AM2/2/16
to django...@googlegroups.com
Yes, those two templates are both entirely the code posted.

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/mAi_fB_MTwo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Martín Torre Castro

unread,
Feb 6, 2016, 8:06:08 PM2/6/16
to django...@googlegroups.com
Solved. Silly error. The name for the template function in the wizard should be get_template_names and it was get_templates_name.

Thank you anyway!!!

Martín Torre Castro

unread,
Feb 7, 2016, 2:47:17 PM2/7/16
to django...@googlegroups.com
James or anyone, the wizard doesn't load the main template for the wizard, just the first step template form. Can you guess why?

James Schneider

unread,
Feb 8, 2016, 4:07:02 AM2/8/16
to django...@googlegroups.com


On Feb 7, 2016 11:46 AM, "Martín Torre Castro" <martin.to...@gmail.com> wrote:
>
> James or anyone, the wizard doesn't load the main template for the wizard, just the first step template form. Can you guess why?
>

The templates you included in your OP didn't have {% extends %} or {% block %} tags in them. I asked about them and you mentioned those are the exact templates you're using. Make sure your step templates have the correct block references in them, otherwise your big parent template will never get loaded. Each step of the form/view renders the entire page, not just the section where the form is at.

-James

Martín Torre Castro

unread,
Feb 8, 2016, 8:36:55 AM2/8/16
to django...@googlegroups.com
If I understand well, you mean that my form templates have to extend the main wizard template. Is that correct?

In previous versions this was achieved by writing template_name = 'main_wizard_template.html' into the subclass of WizardView. Am I wrong?

So, with {% extends 'registration/test_wizard.html' %} in registration/test_step1.html and registration/test_step2.html it should work.

I will try tonight.
Thanks.



-James

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/mAi_fB_MTwo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

James Schneider

unread,
Feb 9, 2016, 3:41:02 AM2/9/16
to django...@googlegroups.com
On Mon, Feb 8, 2016 at 5:36 AM, Martín Torre Castro <martin.to...@gmail.com> wrote:
If I understand well, you mean that my form templates have to extend the main wizard template. Is that correct?

In previous versions this was achieved by writing template_name = 'main_wizard_template.html' into the subclass of WizardView. Am I wrong?

So, with {% extends 'registration/test_wizard.html' %} in registration/test_step1.html and registration/test_step2.html it should work.

I will try tonight.
Thanks.

 
Yes, the templates referenced in each step should extend your main template, if you are doing something fancy in the template used for each step. 

Given the template in your OP, you probably don't even need to specify a template per step, since you aren't doing anything different other than having Django/formtools print the form using the default styling. A simple class attribute like template_name = 'registration/test_wizard.html' would probably suffice, since it should act as the fallback template if you don't specify a template per step, and get rid of get_template_names() entirely (since you're using the same template for every step). Your entire Wizard class can probably look like this:

class WizardTest(SessionWizardView):
    template_name = 'registration/test_wizard.html'

    # Method called when all is done
    def done(self, form_list, **kwargs):
        return HttpResponseRedirect('/url-to-redirect-to/') 

Obviously you'll need to have the other scaffolding in place for this to work (list of forms passed to the view in the urls.py file, etc.), and I don't believe any of the forms will be saved in this state (you'll need to do that as part of your done() method), but everything should display and should give you a base to work from.

-James
Reply all
Reply to author
Forward
0 new messages