Commit 46c17654 authored by Luke Plant's avatar Luke Plant
Browse files

Fixed #14498 - Forms passed to FormWizard.process_step are not guaranteed to have cleaned_data

Thanks to stas for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14290 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 27db9378
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -340,3 +340,23 @@ class WizardTests(TestCase):
                "wizard_step": "1"}
        response = self.client.post('/wizard/', data)
        self.assertEquals(2, response.context['step0'])

    def test_14498(self):
        """
        Regression test for ticket #14498.
        """
        that = self

        class WizardWithProcessStep(WizardClass):
            def process_step(self, request, form, step):
                that.assertTrue(hasattr(form, 'cleaned_data'))

        wizard = WizardWithProcessStep([WizardPageOneForm,
                                        WizardPageTwoForm,
                                        WizardPageThreeForm])
        data = {"0-field": "test",
                "1-field": "test2",
                "hash_0": "7e9cea465f6a10a6fb47fcea65cb9a76350c9a5c",
                "wizard_step": "1"}
        wizard(DummyRequest(POST=data))
+32 −37
Original line number Diff line number Diff line
@@ -90,30 +90,14 @@ class FormWizard(object):
        if current_step >= self.num_steps():
            raise Http404('Step %s does not exist' % current_step)

        # For each previous step, verify the hash and process.
        # TODO: Move "hash_%d" to a method to make it configurable.
        for i in range(current_step):
            form = self.get_form(i, request.POST)
            if not self._check_security_hash(request.POST.get("hash_%d" % i, ''), request, form):
                return self.render_hash_failure(request, i)
            self.process_step(request, form, i)

        # Process the current step. If it's valid, go to the next step or call
        # done(), depending on whether any steps remain.
        if request.method == 'POST':
            form = self.get_form(current_step, request.POST)
        else:
            form = self.get_form(current_step)
        if form.is_valid():
            self.process_step(request, form, current_step)
            next_step = current_step + 1

            # If this was the last step, validate all of the forms one more
            # time, as a sanity check, and call done().
            num = self.num_steps()
            if next_step == num:
                final_form_list = [self.get_form(i, request.POST) for i in range(num)]

        if form.is_valid():
            # Validate all the forms. If any of them fail validation, that
            # must mean the validator relied on some other input, such as
            # an external Web site.
@@ -132,12 +116,23 @@ class FormWizard(object):
            # Since the hashes only take into account values, and not other
            # other validation the form might do, we must re-do validation
            # now for security reasons.
                for i, f in enumerate(final_form_list):
            current_form_list = [self.get_form(i, request.POST) for i in range(current_step)]

            for i, f in enumerate(current_form_list):
                if not self._check_security_hash(request.POST.get("hash_%d" % i, ''), request, f):
                    return self.render_hash_failure(request, i)

                if not f.is_valid():
                    return self.render_revalidation_failure(request, i, f)
                return self.done(request, final_form_list)
                else:
                    self.process_step(request, f, i)

            # Otherwise, move along to the next step.
            # Now progress to processing this step:
            self.process_step(request, form, current_step)
            next_step = current_step + 1

            if current_step == self.num_steps():
                return self.done(request, final_form_list)
            else:
                form = self.get_form(next_step)
                self.step = current_step = next_step