Login

FormWizard inside view with proper context handling and site templating support, without having to use urls.py

Author:
sleepycal
Posted:
December 11, 2009
Language:
Python
Version:
1.1
Tags:
wizard requestcontext views.py form urls.py formwizard views context
Score:
0 (after 0 ratings)

Okay - so I came across a really annoying problem earlier, where I wasn't able to easily load a formwizard as a segment into an existing view, and wrap it using my existing site template layouts. This was REALLY annoying. Especially since I wanted to keep as much of a 'overall' templating and application logic in the views.py (and just leave the forms.py to handle the form and its own templating for the form pages)

I spent about 2 hours trying to make this as conventional as possible, and finally came up with a solution. The result is something which looks as similar to the usual functionality. This also meant that there is seperation between form styling and overall site styling, so your forms can be used between multiple sites, and if your overall site template uses extends, then the context support keeps this nicely in order.

This also allows you to initialise the formwizard in a nicer way.. Of course, in each file, you'll need to import the necessary bits (like importing the testform from the view etc)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
######### libs.py ####################################
# This gives you the extra functionality you'll need 
######################################################
from django.contrib.formtools.wizard import FormWizard

class FormWizardSnip(FormWizard):
    def __init__(self, context):
        # Override the extra context
        self.extra_context = context

        # Call the original init
        super(FormWizardSnip, self).__init__(self._forms)

    def __call__(self, request):
        return super(FormWizardSnip, self).__call__(request)

def render_to_wizard(f, request, context):
    c = f(context=context)
    return c(request)

######## forms.py ####################################
# This is the place where the forms go
######################################################

from django import forms
from django.shortcuts import render_to_response
from webapp.libs import FormWizardSnip
from django.template import RequestContext

class testform_step1(forms.Form):
    subject = forms.CharField(max_length=100)
    sender = forms.EmailField()

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

class testform( FormWizardSnip ):
    # We define the form list here, rather than in the __init__() call. MUCH nicer!!!
    _forms = [CreateNewGateway_step1, CreateNewGateway_step2]

    def get_template(self, step):
        return 'wizard_step%s.html' % step

    def done(self, request, form_list):
        # Compile extra content
        o = self.extra_context
        o['form_data'] = [form.cleaned_data for form in form_list]
        
        # Build the request context
        context = RequestContext(request, o)

        return render_to_response('wizard_done.html', context_instance=context)

######## views.py ####################################
# This is the view function which your urls.py has hit
######################################################
from libs import render_to_wizard
from forms import testform

def test(request):
    # perform your application logic here (user testing etc)

    # Build the request context (this can be used by your overall site templates etc)
    context = {
        'templateOptions'       :   'etc etc'
    }

    # Call the correct parent function with the correct context
    return render_to_wizard(testform, context=context, request=request)



Thats it! I hope this helps someone!

More like this

  1. Complex Form Preview by smagala 5 years, 11 months ago
  2. Ajax form with jQuery by Donn 6 years, 6 months ago
  3. Variable resolving URL template tag by UloPe 5 years, 11 months ago
  4. Effective content caching for mass-load site using redirect feature by nnseva 3 years, 8 months ago
  5. Accessing URL variable from within a Form by blacktav 1 year, 6 months ago

Comments

DimmuR (on September 13, 2010):

First of all - it's great tutorial and thanks for that.

Your _forms should be:

_forms = [testform_step1, testform_step2]

instad of :

_forms = [CreateNewGateway_step1, CreateNewGateway_step2]

Also parsing extra_context didn't work for me but i've manage to find way out by:

changing FormWizardSnip init and call functions to:

class FormWizardSnip(FormWizard):

def __init__(self, context): 
    super(FormWizardSnip, self).__init__(self._forms) 
    self.extra_context = context

def __call__(self, request, *args, **kwargs):
    kwargs = dict(self.extra_context, **kwargs )  
    return super(FormWizardSnip, self).__call__(request, *args, **kwargs)

made it work great. I hope it helps

#

Please login first before commenting.