Django

Code

Ticket #3218 (closed: fixed)

Opened 2 years ago

Last modified 8 months ago

[patch] django.contrib.formtools.wizard proposal

Reported by: Honza Král <Honza.Kral@gmail.com> Assigned to: adrian
Milestone: Component: django.contrib.formtools
Version: SVN Keywords: newforms wizard sprintsept14
Cc: Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz, matt.dorn@gmail.com, join.together@gmail.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

following the discussion http://groups-beta.google.com/group/django-developers/browse_thread/thread/d500c47eb51353e3/2e61103c43fba506?

I have added some more flexibility and cleaned up the code a bit (and added comments ;) ).

Features:

  • just subclass the wizard.Wizard class, override the done() method and you are done - you can just point your urls.py to MyWizard( [list, of, newform, classes] ) and wait...
  • data from previous steps are stored in hidden fields and passed back and forth (do not try and use this for uploading files in any, but the last step of the form ! ), NO data is stored on the server
  • security hash is calculated once the form is validated ( thus you avoid validating each form every time and can detect manual tampering with the POST data)

If that's not enough you can (by overriding/extending some methods):

  • create the list of forms dynamically (you still have to supply at least one form, so that the wizard has something to start with) - do this in process_step() (just append to self.form_list ) -- see the last email for example
  • use a custom template name for every step ( get_template() )
  • override the rendering method for custom rendering ( render_template() )
  • override the mechanism that handles the step counter - by default that is in POST['wizard_step'] , but you can put it in your URL, GET or even session if you wish ( parse_params() )
  • provide extra_context (from urls.py, process_step(), parse_params() etc...)

The only thing that is pretty much hardcoded is the use of POST throughout the wizard.

I am using the code (not the newest version, but I only made cosmeticall changes since) for some time now and everything works.

Once I get some feedback and a few people try it out, I will put together some documentation.

Attachments

wizard.py (7.5 kB) - added by Honza Král <Honza.Kral@gmail.com> on 01/02/07 15:07:22.
wizard_20070111.py (7.8 kB) - added by Honza Král <Honza.Kral@gmail.com> on 01/10/07 18:07:35.
updated version
wizard.2.py (8.3 kB) - added by Honza_Kral on 09/14/07 11:06:48.
matching current trunk (6158)
wizard.3.py (8.1 kB) - added by Honza_Kral on 09/14/07 12:01:02.
matching django's coding style
form_wizard_start_of_tests.diff (13.4 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/14/07 14:33:17.
My test code so far
wizard.4.py (8.3 kB) - added by Honza_Kral on 09/14/07 14:51:36.
validating all forms before invoking done()
form_wizard_start_of_tests.2.diff (12.1 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/14/07 15:39:22.
Test so far, anyone else want to give it a go, i'm suffering from test blindness
wizard.5.py (8.5 kB) - added by Honza_Kral on 09/14/07 16:05:25.
added current_step and step_count
form_wizard_start_of_tests_using_wizard.5.diff (13.3 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/14/07 16:41:29.
Updated to Honza's latest code
form_wizard_hash_tests.diff (13.9 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/14/07 17:44:28.
Test of hashes done
form_wizard_hash_tests_failed_hash_dynamic_form.diff (16.6 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/14/07 18:17:47.
Added some extra tests
form_wizard.txt (3.2 kB) - added by mdorn on 09/15/07 10:49:38.
Updated documentation, final.
form_wizard_with_tests_and_docs_r6199.diff (20.1 kB) - added by Øyvind Saltvik <oyvind@saltvik.no> on 09/16/07 09:04:07.
Complete patch for newforms-admin branch

Change History

01/02/07 15:07:22 changed by Honza Král <Honza.Kral@gmail.com>

  • attachment wizard.py added.

01/10/07 17:45:58 changed by jl@concetto.net

Very nice Honza, I'm already using it in a registration form.

What do you think about a method to navigate through the formlist with html inputs like [< Back] [ Next Step >]? Or is it possible with current wizard.py (01/02/07)?

01/10/07 18:05:41 changed by Honza Král <Honza.Kral@gmail.com>

yes it is, you just press the back button, it will work, or you revert the step to a lower number... but these are all hacks, there is no currently supported way...

I have new version that allows the form to be pre-filled from the previous steps... I will attach it...

01/10/07 18:07:35 changed by Honza Král <Honza.Kral@gmail.com>

  • attachment wizard_20070111.py added.

updated version

01/11/07 05:27:25 changed by Jannis Leidel <jl@concetto.net>

thanks for the initial data function..
unfortunately I don't understand how to use it. could you give a small example like you did on the maillinglist?

regarding the navigational functionality with "back"- and "next"-form submit inputs:

I try to lower self.step within a subclass method "parse_params" by finding out if request.POST.get("navigation") is set (submit input html tag with the name "navigation") and decreasing self.step by 1. strangely it will just work if I decrease by 2 which then breaks the parsing of the template when I want to jump back to form 0 because it wants template wizard-1.html and not wizard0.html. I'm sure this is just an misunderstanding on my side. could you explain a little more?

01/11/07 06:18:51 changed by nervotrepka

  • version changed from SVN to new-admin.
  • component changed from django.contrib.formtools to Unit test system.
  • severity changed from normal to blocker.

5cb16d1ade0a My homepage vvv_5_1 vvv_5_1 vvv_5_2 vvv_5_2 vvv_5_3 vvv_5_3 vvv_5_4 vvv_5_4 vvv_5_5 vvv_5_5

01/12/07 16:06:56 changed by Collin Grady <cgrady@the-magi.us>

  • version changed from new-admin to SVN.
  • component changed from Unit test system to django.contrib.formtools.
  • severity changed from blocker to normal.

01/17/07 17:26:11 changed by Honza Král <Honza.Kral@gmail.com>

  • needs_docs set to 1.

01/19/07 14:57:25 changed by Simon G. <dev@simon.net.nz>

  • stage changed from Unreviewed to Design decision needed.

02/13/07 17:33:36 changed by nick.lane.au@gmail.com

  • cc changed from Honza.Kral@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com.

04/14/07 07:28:06 changed by anonymous

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com.

04/17/07 09:26:58 changed by anonymous

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com.

08/09/07 12:13:02 changed by anonymous

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com.

09/10/07 04:20:08 changed by Honza_Kral

  • owner changed from nobody to Honza_Kral.

09/10/07 04:38:54 changed by david

There is an interesting snippet about that: http://www.djangosnippets.org/snippets/222/

09/12/07 10:01:57 changed by anonymous

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz.

09/14/07 11:06:48 changed by Honza_Kral

  • attachment wizard.2.py added.

matching current trunk (6158)

09/14/07 11:10:23 changed by adrian

  • stage changed from Design decision needed to Accepted.

This is a cool idea. Before we can check it in, though, it needs docs and tests.

09/14/07 11:23:25 changed by mdorn

  • owner changed from Honza_Kral to mdorn.
  • status changed from new to assigned.

working on docs and tests

09/14/07 11:31:19 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • keywords changed from newforms wizard to newforms wizard sprintsept14.

09/14/07 12:01:02 changed by Honza_Kral

  • attachment wizard.3.py added.

matching django's coding style

09/14/07 14:33:17 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_start_of_tests.diff added.

My test code so far

09/14/07 14:51:36 changed by Honza_Kral

  • attachment wizard.4.py added.

validating all forms before invoking done()

09/14/07 15:39:22 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_start_of_tests.2.diff added.

Test so far, anyone else want to give it a go, i'm suffering from test blindness

09/14/07 16:05:25 changed by Honza_Kral

  • attachment wizard.5.py added.

added current_step and step_count

09/14/07 16:41:29 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_start_of_tests_using_wizard.5.diff added.

Updated to Honza's latest code

09/14/07 17:44:28 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_hash_tests.diff added.

Test of hashes done

09/14/07 18:17:47 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_hash_tests_failed_hash_dynamic_form.diff added.

Added some extra tests

09/15/07 10:49:38 changed by mdorn

  • attachment form_wizard.txt added.

Updated documentation, final.

09/15/07 10:52:42 changed by mdorn

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz, matt.dorn@gmail.com.
  • owner changed from mdorn to Honza_Kral.
  • status changed from assigned to new.

Documentation finished, reassigning to Honza, so he can double-check before moving to check-in

09/15/07 10:55:00 changed by mdorn

  • needs_docs deleted.

09/16/07 09:04:07 changed by Øyvind Saltvik <oyvind@saltvik.no>

  • attachment form_wizard_with_tests_and_docs_r6199.diff added.

Complete patch for newforms-admin branch

(follow-up: ↓ 21 ) 10/18/07 13:33:55 changed by jstritar@gmail.com

Since the previous step's data is kept as POST parameters, there isn't a nice way to go back to a previous step (other than the back button). I think something like this is an important usability feature (think of a checkout process where you can click previous steps if you made a mistake).

Example:

| 1 | 2 | 3 | 4 |

I am on step 4. I click the 2, loading the 2nd step with the data I originally entered.

(in reply to: ↑ 20 ) 10/18/07 13:37:07 changed by Honza_Kral

Replying to jstritar@gmail.com:

Since the previous step's data is kept as POST parameters, there isn't a nice way to go back to a previous step (other than the back button). I think something like this is an important usability feature (think of a checkout process where you can click previous steps if you made a mistake). Example: | 1 | 2 | 3 | 4 | I am on step 4. I click the 2, loading the 2nd step with the data I originally entered.

I thought that wouldn't be the common usage, but you can achieve that via overriding the parse_params method, you can derive self.step from URL, GET or any other means you feel like...

(follow-up: ↓ 23 ) 10/18/07 14:09:02 changed by Jon Stritar <jstritar@gmail.com>

You'd be able to pass the step via a URL or GET parameter, but the Forms up to and including that step wouldn't have any data (since there wasn't a POST).

(in reply to: ↑ 22 ; follow-up: ↓ 24 ) 10/18/07 17:41:36 changed by Honza_Kral

Replying to Jon Stritar <jstritar@gmail.com>:

You'd be able to pass the step via a URL or GET parameter, but the Forms up to and including that step wouldn't have any data (since there wasn't a POST).

true, haven't actually thought it through this far... I guess the only option is to have the form post the data with the appropriate step value - you won't avoid a form or some javascript...

I a generally opposed to the idea of storing the data on server-side it doesn't make much sense, adds a lot of additional complexity and dependency on sessions and/or some other form of storing the data...

(in reply to: ↑ 23 ; follow-up: ↓ 25 ) 10/30/07 04:05:34 changed by anonymous

Replying to Honza_Kral:

I a generally opposed to the idea of storing the data on server-side it doesn't make much sense, adds a lot of additional complexity and dependency on sessions and/or some other form of storing the data...

I think what we are talking about here is state, and isn't maintaining state exactly what sessions are for in an otherwise stateless protocol? I know that it is more elegant to minimize dependancies, but depending on the sessions framework is justified here imho.

(in reply to: ↑ 24 ) 10/30/07 04:09:06 changed by remco@diji.biz

oops didn't want to show as an anonymous coward :)

12/22/07 14:43:57 changed by anonymous

what is the status of this bug?

I tested the diffs with 0.97-pre-SVN-6971 and it didn't work for me. :(

02/26/08 16:37:17 changed by adrian

  • owner changed from Honza_Kral to adrian.
  • status changed from new to assigned.

I have an immediate need for this for a project, so I'll take the lead on reviewing and checking it in.

03/13/08 15:12:53 changed by adrian

  • status changed from assigned to closed.
  • resolution set to fixed.

(In [7236]) Fixed #3218 -- Implemented django.contrib.formtools.wizard. Thanks, Honza and Oyvind. Note that there are no docs yet

(follow-up: ↓ 30 ) 04/18/08 15:29:56 changed by anonymous

  • cc changed from Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz, matt.dorn@gmail.com to Honza.Kral@gmail.com, nick.lane.au@gmail.com, larlet@gmail.com, jesse.lovelace@gmail.com, allandouglas@gmail.com, remco@diji.biz, matt.dorn@gmail.com, join.together@gmail.com.

I know a lot of people have cc'd this, so i'll ask this here before making a ticket out of it in the hopes that someone can answer.

When calculating the hash, why dose it use unclean data? I've found a bug that causes Booleanfields that are set to false to erroneously cause the hash tst

(On the first pass, the value for the field is calculated to be (empty string), but the next time you try to submit something it's somehow False now, so the data is different than it was previously so the test fails and you have to start over.)

I would gladly write a patch that has it pull the data to be hashed from form.cleaned data, but before I do is there a reason why it doesn't already do that?

(in reply to: ↑ 29 ) 04/18/08 18:55:48 changed by Honza_Kral

Replying to anonymous:

I know a lot of people have cc'd this, so i'll ask this here before making a ticket out of it in the hopes that someone can answer. When calculating the hash, why dose it use unclean data?

because than we can make tests without doing the clean(), which may be an expensive operation... so we don't have to validate every data on every pass...


Add/Change #3218 ([patch] django.contrib.formtools.wizard proposal)




Change Properties
Action