Opened 17 years ago
Last modified 13 years ago
#7038 closed
FormWizard fails on forms with BooleanField when field is unselected — at Version 5
Reported by: | anonymous | Owned by: | nobody |
---|---|---|---|
Component: | contrib.formtools | Version: | dev |
Severity: | Keywords: | FormWizard, BooleanField, hash failure | |
Cc: | rajesh.dhawan@…, dev@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
The form wizard fails to match its security hash when processing a form containing at least one BooleanField where the BooleanField's checkbox is unselected (e.g. False). This results in (on my machine) the form containing the BooleanField being redisplayed. If *all* the BooleanFields on a form are selected, it appears to work correctly.
I was able to workaround (not fix) by overriding the security_hash method as follows:
def security_hash(self, request, form): for bf in form: if bf.field.__class__ != BooleanField: data = [(bf.name, bf.data or u'')] + [settings.SECRET_KEY] # Use HIGHEST_PROTOCOL because it's the most efficient. It requires # Python 2.3, but Django requires 2.3 anyway, so that's OK. pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL) return md5.new(pickled).hexdigest()
The problem appears (to my untrained eye) to be in the line assigning the value of data where bf.data = False and thus gets assigned .
I'm using SVN 7412.
Change History (6)
comment:1 by , 17 years ago
Component: | Uncategorized → django.contrib.formtools |
---|
follow-up: 4 comment:2 by , 17 years ago
comment:3 by , 17 years ago
Keywords: | hash failure added |
---|
I get this also... not an easy bug to detect when one has a wizard with many forms! maybe a better solution would be to explicitly set every unset BooleanField to False as soon as possible, that is: well before the hashing?
comment:4 by , 17 years ago
Replying to tbye@tbye.com:
When attempting to use the sample workaround above with rev. 7545 I hit an issue. Here's my updated sample to correct the problems I ran into.
def security_hash(self, request, form):
for bf in form:
if bf.field != BooleanField:
data = [(bf.name, bf.data or )] + [settings.SECRET_KEY]
This also means that only the last field per form, whatever that is, is hashed at all, as 'data' is replaced for almost every trip through the 'for'. Ergo, one might as well not have the hashing at all.
The real problem is that sql and web and boolean logic disagrees as to what a checkbox (CheckboxInput in django's case) is supposed to mean. Sql has three values for a bool: true, false, and unset. Web only has on/True and unset. Django has two types of boolean fields, using the same widget: BooleanField, which must be set and has two possible values: True and False, and NullboleanField, which is like sql in that it has three values: True, False and None (unset). The checkbox-widget however, obeys the web-rule of True vs. unset and ergo doesn't really fit with either of the fields =) See also #7051, #7190, #6937, #6914, #5957
comment:5 by , 16 years ago
Description: | modified (diff) |
---|
by , 16 years ago
Attachment: | django.contrib.formtools.7828.patch added |
---|
django.contrib.formtools.7828.patch
When attempting to use the sample workaround above with rev. 7545 I hit an issue. Here's my updated sample to correct the problems I ran into.