#3218 closed enhancement (fixed)
[patch] django.contrib.formtools.wizard proposal
Reported by: | Owned by: | Adrian Holovaty | |
---|---|---|---|
Component: | contrib.formtools | Version: | dev |
Severity: | normal | Keywords: | newforms wizard sprintsept14 |
Cc: | Honza.Kral@…, nick.lane.au@…, larlet@…, jesse.lovelace@…, allandouglas@…, remco@…, matt.dorn@…, join.together@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
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 toMyWizard( [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 toself.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 (13)
Change History (43)
by , 18 years ago
comment:1 by , 18 years ago
comment:2 by , 18 years ago
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...
comment:3 by , 18 years ago
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?
comment:4 by , 18 years ago
Component: | django.contrib.formtools → Unit test system |
---|---|
Severity: | normal → blocker |
Version: | SVN → new-admin |
comment:5 by , 18 years ago
Component: | Unit test system → django.contrib.formtools |
---|---|
Severity: | blocker → normal |
Version: | new-admin → SVN |
comment:6 by , 18 years ago
Needs documentation: | set |
---|
comment:7 by , 18 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:8 by , 18 years ago
Cc: | added |
---|
comment:9 by , 18 years ago
Cc: | added |
---|
comment:10 by , 18 years ago
Cc: | added |
---|
comment:11 by , 17 years ago
Cc: | added |
---|
comment:12 by , 17 years ago
Owner: | changed from | to
---|
comment:13 by , 17 years ago
There is an interesting snippet about that: http://www.djangosnippets.org/snippets/222/
comment:14 by , 17 years ago
Cc: | added |
---|
comment:15 by , 17 years ago
Triage Stage: | Design decision needed → Accepted |
---|
This is a cool idea. Before we can check it in, though, it needs docs and tests.
comment:16 by , 17 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
working on docs and tests
comment:17 by , 17 years ago
Keywords: | sprintsept14 added |
---|
by , 17 years ago
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
by , 17 years ago
Attachment: | form_wizard_start_of_tests_using_wizard.5.diff added |
---|
Updated to Honza's latest code
by , 17 years ago
Attachment: | form_wizard_hash_tests_failed_hash_dynamic_form.diff added |
---|
Added some extra tests
comment:18 by , 17 years ago
Cc: | added |
---|---|
Owner: | changed from | to
Status: | assigned → new |
Documentation finished, reassigning to Honza, so he can double-check before moving to check-in
comment:19 by , 17 years ago
Needs documentation: | unset |
---|
by , 17 years ago
Attachment: | form_wizard_with_tests_and_docs_r6199.diff added |
---|
Complete patch for newforms-admin branch
follow-up: 21 comment:20 by , 17 years ago
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.
comment:21 by , 17 years ago
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 comment:22 by , 17 years ago
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).
follow-up: 24 comment:23 by , 17 years ago
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...
follow-up: 25 comment:24 by , 17 years ago
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.
comment:26 by , 17 years ago
what is the status of this bug?
I tested the diffs with 0.97-pre-SVN-6971 and it didn't work for me. :(
comment:27 by , 17 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
I have an immediate need for this for a project, so I'll take the lead on reviewing and checking it in.
comment:28 by , 17 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
follow-up: 30 comment:29 by , 17 years ago
Cc: | added |
---|
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?
comment:30 by , 17 years ago
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...
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)?