Dan Ward Follow me on Twitter View my LinkedIn profile Subscribe to my news feed   

A self-confessed geek and web developer


Blog: Using Django's FormWizard with one or more ModelForm's

From time-to-time, I'll have a brainwave while trying to figure out something tech-oriented; well, either that or I just want to get something off my chest. Anyhow, if I get round to typing it up, it'll wind up here in the blog.

Created by dan on Thursday 18th March, 2010 at 3:11 PM
Tags: Web development, Django, Python

I've been looking at Django's form wizard implementation over the past day or so and learned quite a few new things, but one of them caught me out, yet only required a simple fix.

Django appears to focus more on creating a FormWizard to work with flat forms, however if you wish to instantiate a model form, it's a little more vague. This is where looking through Django's code reveals the answer.

The below code does the trick for me at least. OK, it's not perfect but it's simple enough and does the job. Pop this in your FormWizard and read further.

    def get_form(self, step, data=None):
        if step == 0 and hasattr(self, 'request') and hasattr(self.request, 'user') and self.request.user.is_authenticated():
            return self.form_list[step](data, prefix=self.prefix_for_step(step), initial=self.initial.get(step, None), instance=self.request.user)
        return self.form_list[step](data, prefix=self.prefix_for_step(step), initial=self.initial.get(step, None))
    def __call__(self, request, *args, **kwargs):
        self.request = request
        return super(self.__class__, self).__call__(request, *args, **kwargs)

The __call__ method can remain as-is, however the get_form method may require some tweaking for your requirements. In my case, the first step (0) serves a ModelForm (the rest does not), so for this form only, I've added in a condition to check for valid request data for an authenticated user (set in the __call__ method). If all is well, it'll provide an instance to the ModelForm for you.

Simple enough.