Django Form Wizard and Getting Data from Previous Steps

I’ve spent the last few days implementing a Django SessionWizardView and ran into what I thought would be a simple problem – how to access the data of a previous form in order to initialize a later form (i.e. use data submitted on step 1 to initialize the step 3 form). Google didn’t turn up much so I turned to the documentation for a solution.

At first glance it seemed simple enough – use get_cleaned_data_for_step or get_all_cleaned_data. The problem with these, I quickly discovered, is that they call get_form which in turn calls get_form_initial (which is where I’m trying to use the submitted form data in the first place). So that was a dead end.

Next up was using get_form_step_data. This method is called before get_form_initial and has access to both the form’s data and cleaned_data properties. The issue with this technique, however, is that it would require the data to be stored in some way for use in get_form_initial (either via a session variable or an instance variable). While this works, it still seemed like there had to be a better way. After all, the wizard is storing this data somewhere already.

So after a bit of digging in the source, the solution was obvious –

This method allows you to pull the data from any step and will return either None or a MultiValueDict.

One final thing to note is that because get_form_initial is called for every previous step (with that previous step as the step argument), it’s probably likely you’ll need to know what step you’re actually on. You can do this by using

If anyone knows of a better way to do this, I’d love to know.

5 thoughts on “Django Form Wizard and Getting Data from Previous Steps”

  1. Interesting approach, I’ve bumped into this problem as well, the only downside of your solution, is you don’t get the “cleaned” value, so in case of date, datetime, you need to parse it manually, but I guess that’s small price to pay comparing to overkill with regenerating prev forms, especially if there’s sql involved in form init..
    Anyway thanks for the tip. Hope to see more😉

    1. Actually you do get the cleaned data. If you look at the method definition for set_step_data, you’ll see that the cleaned_data is what is being saved to the storage:

      def get_step_data(self, step):
          # When reading the serialized data, upconvert it to a MultiValueDict,
          # some serializers (json) don't preserve the type of the object.
          values =[self.step_data_key].get(step, None)
          if values is not None:
              values = MultiValueDict(values)
          return values
      def set_step_data(self, step, cleaned_data):
          # If the value is a MultiValueDict, convert it to a regular dict of the
          # underlying contents.  Some serializers call the public API on it (as
          # opposed to the underlying dict methods), in which case the content
          # can be truncated (__getitem__ returns only the first item).
          if isinstance(cleaned_data, MultiValueDict):
              cleaned_data = dict(cleaned_data.lists())
[self.step_data_key][step] = cleaned_data
  2. Ran into the same issue. A simple way to get all the step data in the context is to append it using get_context_data and get_all_cleaned_data.

    def get_context_data(self, form, **kwargs):
    context = super(MyWizard, self).get_context_data(form=form, **kwargs)
    context[‘wizard_data’] = self.get_all_cleaned_data()
    return context

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s