David, > Not only. I also tried to allow steps (=views) to completely move away > from the current form based approach. This means each step can decide > what to to on a view-like-level (render a form, issue an redirect, or > just display a simple template). I don't see this is possible with > WizardView, as the wizard sure can decide this, but never the step (=form)?
The step gets whatever data you need, use the get_form_kwargs() method. > The use-case I have in mind is a registration wizard where you probably > need to switch to foreign sites (for example paypal payment) and later > need to continue the wizard where you left. I decided to implement this > using an HttpResponseRedirect inside the payment-step-view. After > getting back into the wizard GET-params will tell what happened (if > payment succeeded). So there is no form involved here. Use the render() method to override the default response behavior. > Besides this having class based views as steps inside the wizard also > may create more reusable code. Most of the time registrations-forms will > be used again to handle account-changes (e.g. update payment data). > Having a class based view here in the first place makes this an > no-brainer (you probably need to switch the template). At the same time > creating a view-based wizard is not that complicated compared to the > form-wizard, there could even be a form-wizard-class which just > initializes the view-wizard-class the right way. That's a baseless assumption, views are much more complex than simple forms and serve a different purpose. So speaking of a no-brainer to "compose" such a wizard out of different views is with all due respect over the top. If at all it's more complicated for the common use case. > To pick up my example above: > I could issue the HttpResponseRedirect inside render_next_step() of > WizardView. But if the user comes back this will always be a > GET-request, so I have to overwrite get() as the default implementation > resets the storage. In addition I need to provide some (useless) form > for the payment step, which I will need to fill with dummy data to get > it validating. This means fiddling a lot inside the WizardView internals. The purpose of the class-based views *is* to overwrite methods like get(). > In addition I want to provide another use case, still regarding handling > payment: > In our first version we had multiple steps for handling payment. The > first one was just used to allow the user to choose the payment method > using a simple form. The following steps where forms for each method > (credit card, etc), filtered using conditions to just show the right one > (so the user always saw two steps). This all worked fine until we > decided to merge the whole payment process into one step. Now the step > needs to consist of multiple forms, which was very easy to implement > using a view where the developer can decide how to handle the request. > Actually this step is based on a simple TemplateView, just implementing > get()/post(), providing multiple forms to the template. I don't see compelling proof that this is impossible with the current implementation. > Another thing that got much easier was the ProfileView (step where the > user enters his/her personal data). This step initially consisted of > four forms, one of these where selected using conditions (if "user is > logged in" and "payment is needed"). After having a FormView I could > more these four steps to just one view (based on FormView) implementing > get_form_class(). I didn't even need to implement the four forms this > way, as I could just change form.base_field to remove unneeded fields. > > There might be other valid use cases. That's not convincing enough for me to consider a major shift of a contrib app. > Having each step implemented as a class-based view itself provides much > more data to the step itself (request, args, kwargs, etc -> params you > usually don't have inside forms). In addition the view itself handles > how the request gets processed (-> dispatch()) so the step itself gets > much more power over the whole process. As I said above, the form gets passed whatever you give it from the views, see the get_form_kwargs method. > I have put up my (hacky) proof of concept on dpaste: > http://dpaste.org/SWhn/ How is it used? > This currenly uses the formwizard storage backend, so this is definately > a dependency. In addition it is heavily based on formwizard, so it > currenly is not implemented as a View like WizardView. FYI, the FormWizard class is deprecated. > Anyway, I just thought this to be a good and slightly more generic > approach, made possible thanks to the new class based views we got in > 1.3. If this of to far away from the default use case for django core I > will try to move this into a third party app. Currently I think I can > reuse much of the code you and Stephan wrote to implement WizardView > (for example the storage system), which is nice. I haven't seen compelling reason to consider this a "slightly more generic" approach, but simply a "different" approach to view compositing. In that sense I'm -0 on it since it just stands for "another opinion", and arguably a "better" one. Let's hope that other developers chime in since obviously YMMV. Jannis -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
