views:

541

answers:

2

I'm trying to create a simple Django multi-page form using FormWizard. What the form should do is the following:

  1. Let the visitor enter first and lastname in a form.
  2. Continue to next page where entered previously firstname and lastname will be displayed, there will also be a field on this page that let's the visitor enter a message.
  3. The visistor will be taken to the Django done.html page where all information will be stored and displayed.

In step 2, I'm having trouble figuring out how to display the information that the visitor entered in step 1. I'm posting the code for the forms and the two templates used for step 1 and 2 below:

forms.py

from django import forms
from django.shortcuts import render_to_response
from django.contrib.formtools.wizard import FormWizard

class ContactWizard(FormWizard):
 def done(self, request, form_list):
  return render_to_response('done.html', {
   'form_data': [form.cleaned_data for form in form_list],
  })

 def get_template(self, step):
  return 'buydomain/templates/reg%s.html' % step

class Form1(forms.Form):
 firstName = forms.CharField()
 lastName = forms.CharField()

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

template for step 1:

{% block content %}
<p>Step {{ step }} of {{ step_count }}</p>
<form action="." method="post">
<table>
{{ form }}
</table>
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />
{{ previous_fields|safe }}
<input type="submit">
</form>
{% endblock %}

template for step 2:

{% block content %}
<p>Step {{ step }} of {{ step_count }}</p>


{% comment %}
Show values entered into Form1 here !
{% endcomment %}

<form action="." method="post">
<table>
{{ form }}
</table>
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />
{{ previous_fields|safe }}
<input type="submit">
</form>
{% endblock %}

I apologize if I'm somewhat unclear about what I want to achieve, and I'm hopefully waiting for someone to supply a solution. Thanks in advance.

+2  A: 

Just some general advice first - if you don't understand how to use something in Django, pull out that text editor and take a look at the code. It's not always the fastest way to get an answer, but I believe it pays dividends in the long run.

Try adding some extra_context to the second step by overriding process_step in your FormWizard subclass. Here are the comments from within FormWizard (django 1.1):

 def process_step(self, request, form, step):
        """
        Hook for modifying the FormWizard's internal state, given a fully
        validated Form object. The Form is guaranteed to have clean, valid
        data.

        This method should *not* modify any of that data. Rather, it might want
        to set self.extra_context or dynamically alter self.form_list, based on
        previously submitted forms.

        Note that this method is called every time a page is rendered for *all*
        submitted steps.
        """
        pass

so in your own ContactWizard class, something like (NB: I did not compile this):

class ContactWizard(FormWizard):
    def process_step(self,request,form,step):
        if step == 1:
            self.extra_context = {'whatever': form.whatever_you_want_from_the_form}
            return
        else:
            return
tobypanzer
How does the subsequent form class access the extra_context data?
BozoJoe
+2  A: 

I don't know if it's useful to still post this solution. Nevertheless. Needing stuff between the different forms (steps) used by the Wizard, are easily accessible when you give the wizard an extra attrib in the form of a dict. Like so:

class WizardRegistration(FormWizard):
    def __init__(self, *args, **kwargs):
        super(WizardRegistration, self).__init__(*args, **kwargs)

        setattr(self, 'chosen', {})

Between the steps you can then easily take form or Model stuff and store it until you reach the done() method. Store a form value

self.chosen['something_to_store'] = form.cleaned_data.get('a_form_value')

Or even get/change/save a model:

object = Model.objects.get('some_query')

if self.chosen['object']:
    self.chosen['object'].string = 'Something stringy'
    self.chosen['object'].save()
GerardJP