diff --git a/django/contrib/formtools/tests/wizard/forms.py b/django/contrib/formtools/tests/wizard/forms.py index f6e177e5a4a..14c6e6a6858 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 cba39151e79..4379e6cdebd 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 bcffb7716b8..f8d46fd2914 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