From b614c47f8c05f8c29a974dac984d0f07c3a09fce Mon Sep 17 00:00:00 2001
From: Stephan Jaekel <steph@rdev.info>
Date: Sat, 12 Jan 2013 13:09:30 +0100
Subject: [PATCH] Added some class attributes to pass initial form lists to the
 WizardView without the need to add them in the as_view call.

---
 .../contrib/formtools/tests/wizard/forms.py   | 29 +++++++++++++++++++
 django/contrib/formtools/wizard/views.py      | 28 +++++++++++-------
 docs/ref/contrib/formtools/form-wizard.txt    | 20 +++++++++++++
 3 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/django/contrib/formtools/tests/wizard/forms.py b/django/contrib/formtools/tests/wizard/forms.py
index f6e177e5a4..14c6e6a685 100644
--- a/django/contrib/formtools/tests/wizard/forms.py
+++ b/django/contrib/formtools/tests/wizard/forms.py
@@ -78,6 +78,12 @@ class TestWizard(WizardView):
             kwargs['test'] = True
         return kwargs
 
+class TestWizardWithInitAttrs(TestWizard):
+    form_list = [Step1, Step2]
+    condition_dict = {'step2': True}
+    initial_dict = {'start': {'name': 'value1'}}
+    instance_dict = {'start': User()}
+
 class FormTests(TestCase):
     def test_form_init(self):
         testform = TestWizard.get_initkwargs([Step1, Step2])
@@ -91,6 +97,9 @@ class FormTests(TestCase):
         self.assertEqual(
             testform['form_list'], {'0': Step1, '1': Step2, 'finish': Step3})
 
+        testform = TestWizardWithInitAttrs.get_initkwargs()
+        self.assertEqual(testform['form_list'], {'0': Step1, '1': Step2})
+
     def test_first_step(self):
         request = get_request()
 
@@ -132,6 +141,11 @@ class FormTests(TestCase):
         response, instance = testform(request)
         self.assertEqual(instance.get_next_step(), 'step3')
 
+        testform = TestWizardWithInitAttrs.as_view(
+            [('start', Step1), ('step2', Step2), ('step3', Step3)])
+        response, instance = testform(request)
+        self.assertEqual(instance.get_next_step(), 'step2')
+
     def test_form_kwargs(self):
         request = get_request()
 
@@ -162,6 +176,13 @@ class FormTests(TestCase):
         self.assertEqual(instance.get_form_initial('start'), {'name': 'value1'})
         self.assertEqual(instance.get_form_initial('step2'), {})
 
+        testform = TestWizardWithInitAttrs.as_view(
+            [('start', Step1), ('step2', Step2)])
+        response, instance = testform(request)
+
+        self.assertEqual(instance.get_form_initial('start'), {'name': 'value1'})
+        self.assertEqual(instance.get_form_initial('step2'), {})
+
     def test_form_instance(self):
         request = get_request()
         the_instance = TestModel()
@@ -176,6 +197,14 @@ class FormTests(TestCase):
             instance.get_form_instance('non_exist_instance'),
             None)
 
+        testform = TestWizardWithInitAttrs.as_view(
+            [('start', TestModelForm), ('step2', Step2)])
+        response, instance = testform(request)
+
+        self.assertEqual(
+            instance.get_form_instance('start'),
+            TestWizardWithInitAttrs.instance_dict['start'])
+
     def test_formset_instance(self):
         request = get_request()
         the_instance1, created = TestModel.objects.get_or_create(
diff --git a/django/contrib/formtools/wizard/views.py b/django/contrib/formtools/wizard/views.py
index cba39151e7..4379e6cdeb 100644
--- a/django/contrib/formtools/wizard/views.py
+++ b/django/contrib/formtools/wizard/views.py
@@ -120,8 +120,8 @@ class WizardView(TemplateView):
         return super(WizardView, cls).as_view(**initkwargs)
 
     @classmethod
-    def get_initkwargs(cls, form_list, initial_dict=None,
-            instance_dict=None, condition_dict=None, *args, **kwargs):
+    def get_initkwargs(cls, form_list=None, initial_dict=None,
+        instance_dict=None, condition_dict=None, *args, **kwargs):
         """
         Creates a dict with all needed parameters for the form wizard instances.
 
@@ -144,12 +144,20 @@ class WizardView(TemplateView):
           will be called with the wizardview instance as the only argument.
           If the return value is true, the step's form will be used.
         """
+
         kwargs.update({
-            'initial_dict': initial_dict or {},
-            'instance_dict': instance_dict or {},
-            'condition_dict': condition_dict or {},
+            'initial_dict': initial_dict or kwargs.pop('initial_dict',
+                getattr(cls, 'initial_dict', None)) or {},
+            'instance_dict': instance_dict or kwargs.pop('instance_dict',
+                getattr(cls, 'instance_dict', None)) or {},
+            'condition_dict': condition_dict or kwargs.pop('condition_dict',
+                getattr(cls, 'condition_dict', None)) or {}
         })
-        init_form_list = SortedDict()
+
+        form_list = form_list or kwargs.pop('form_list',
+            getattr(cls, 'form_list', None)) or []
+
+        computed_form_list = SortedDict()
 
         assert len(form_list) > 0, 'at least one form is needed'
 
@@ -158,13 +166,13 @@ class WizardView(TemplateView):
             if isinstance(form, (list, tuple)):
                 # if the element is a tuple, add the tuple to the new created
                 # sorted dictionary.
-                init_form_list[six.text_type(form[0])] = form[1]
+                computed_form_list[six.text_type(form[0])] = form[1]
             else:
                 # if not, add the form with a zero based counter as unicode
-                init_form_list[six.text_type(i)] = form
+                computed_form_list[six.text_type(i)] = form
 
         # walk through the new created list of forms
-        for form in six.itervalues(init_form_list):
+        for form in six.itervalues(computed_form_list):
             if issubclass(form, formsets.BaseFormSet):
                 # if the element is based on BaseFormSet (FormSet/ModelFormSet)
                 # we need to override the form variable.
@@ -179,7 +187,7 @@ class WizardView(TemplateView):
                             "wizard view in order to handle file uploads.")
 
         # build the kwargs for the wizardview instances
-        kwargs['form_list'] = init_form_list
+        kwargs['form_list'] = computed_form_list
         return kwargs
 
     def get_prefix(self, *args, **kwargs):
diff --git a/docs/ref/contrib/formtools/form-wizard.txt b/docs/ref/contrib/formtools/form-wizard.txt
index bcffb7716b..f8d46fd291 100644
--- a/docs/ref/contrib/formtools/form-wizard.txt
+++ b/docs/ref/contrib/formtools/form-wizard.txt
@@ -245,6 +245,13 @@ wizard's ``as_view()`` method takes a list of your
         (r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
     )
 
+.. versionchanged:: 1.6
+
+You can also pass the form list as a class attribute named ``form_list``.
+
+    class ContactWizard(WizardView):
+        form_list = [ContactForm1, ContactForm2]
+
 .. _wizard-template-for-each-form:
 
 Using a different template for each form
@@ -295,6 +302,14 @@ The ``urls.py`` file would contain something like::
         (r'^checkout/$', OrderWizard.as_view(FORMS, condition_dict={'cc': pay_by_credit_card})),
     )
 
+.. versionchanged:: 1.6
+
+The ``condiction_dict`` can be passed as attribute for the ``as_view()``
+method or as a class attribute named ``condition_dict``.
+
+    class OrderWizard(WizardView):
+        condition_dict = {'cc': pay_by_credit_card}
+
 Note that the ``OrderWizard`` object is initialized with a list of pairs.
 The first element in the pair is a string that corresponds to the name of the
 step and the second is the form class.
@@ -550,6 +565,11 @@ Providing initial data for the forms
     The ``initial_dict`` can also take a list of dictionaries for a specific
     step if the step is a ``FormSet``.
 
+    .. versionchanged:: 1.6
+
+    The ``initial_dict`` can also be added as a class attribute named
+    ``initial_dict`` to avoid having the initial data in the ``urls.py``.
+
 .. _wizard-files:
 
 Handling files