Question

I'm trying use the FormWizard for to submit an order "charge" in wizard done method. Extending the example in the documentation, performing the credit card "charge" in the done means you can't go back and reprompt for credit card, because the wizard performs self.storage.reset() after calling the done method.

What is the right approach? The confirmation form clean() step is called multiple times for revalidation, etc, & seems too removed from done() where all validated forms are available.

Thanks for any pointers.

Kent

Was it helpful?

Solution 2

I guess the answer is "you can't get there from here". I opened a ticket #19189, but it's unclear this feature will be added.

OTHER TIPS

I could think of this:

  • In done() method you will be charging the user. If its declined/failed, save each forms data in session/cookies.
  • Restart the wizard from specific step where payment info is taken. NamedUrlWizard might be helpful.
  • Implement your get_form_intial() to return data from session/cookies for the step.

However, I think validation of this may fail as skipped steps do not have data. So you may have to do some more to get pass that.

Here is my solution: 1. extend WizardView, modify render_done method to catch exception in it: - detailed description

from django.contrib.formtools.wizard.views import SessionWizardView

class MySessionWizardView(SessionWizardView):

    def __init__(self, **kwargs):
        super(MySessionWizardView, self).__init__(**kwargs)
        self.has_errors = False

    class RevalidationError(Exception):
        def __init__(self, step, form, **kwargs):
            self.step = step
            self.form = form
            self.kwargs = kwargs

        def __repr__(self):
            return '%s(%s)' % (self.__class__, self.step)
        __str__ = __repr__

    def render_done(self, form, **kwargs):
        final_form_list = []
        for form_key in self.get_form_list():
            form_obj = self.get_form(step=form_key,
                data=self.storage.get_step_data(form_key),
                files=self.storage.get_step_files(form_key))
            if not form_obj.is_valid():
                return self.render_revalidation_failure(form_key, form_obj, **kwargs)
            final_form_list.append(form_obj)

        try:
            done_response = super(MySessionWizardView, self).render_done(form, **kwargs)
        except self.RevalidationError as e:
            return self.render_revalidation_failure(e.step, e.form, **e.kwargs)
        self.storage.reset()
        return done_response
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top