#11303: changed_data works incorrectly with BooleanField
-------------------------------+--------------------------------------------
          Reporter:  oduvan    |         Owner:  nobody
            Status:  new       |     Milestone:        
         Component:  Forms     |       Version:  1.1   
        Resolution:            |      Keywords:        
             Stage:  Accepted  |     Has_patch:  1     
        Needs_docs:  0         |   Needs_tests:  0     
Needs_better_patch:  0         |  
-------------------------------+--------------------------------------------
Changes (by semenov):

  * version:  1.1-beta-1 => 1.1
  * summary:  changed_data wrong work with BooleanField => changed_data
              works incorrectly with BooleanField

Comment:

 I agree with @margieroginski. The current show_hidden_input implementation
 is just broken when it comes to booleans/checkboxes. @russellm, this isn't
 an "edge case annoyance...in the admin" at all. The show_hidden_input
 logic is '''very''' useful when you allow to edit a single (shared) model
 instance to many users simultaneously; they won't be posting "old" data
 and rewrite all changes made by the other collaborators. You shouldn't
 underestimate the importance, as this is actually a very common use case -
 that would be useful even in ''this Django bug tracker'', since that's not
 a rare situation when someone's changes to Summary or Triage Stage is
 erroneously "reverted" by the next poster - a perfect example where hidden
 inputs should have been added.

 I found this ticket because I first developed ''my own'' generic
 implementation of exactly the same logic - I was saving pristine values
 along with the form and then checking them on submit. Then I discovered
 the show_hidden_input parameter and rewrote my app to use it instead. The
 funny thing is that in my implementation, I didn't have the discussed bug
 since I was testing on a form which had BooleanFields from the very
 beginning so I specifically added a workaround. You can imagine my
 disappointment when my code suddenly broke when switched to the "original"
 Django solution.[[br]][[br]]

 > In general it seems very difficult to compare all these values such as
 False, 'False', u'0', u'1', True, 'True' and get it right.

 I can't agree with that. Overestimating the complexity of the problem is
 no better than underestimating its importance :)[[br]]
 There's no such things as 'False'. How did you get that? When a python
 value is rendered, it gets through force_unicode() and False can only
 become '0'. Therefore, the logic is very simple:[[br]]
 1) no data, !'' and '0' is False[[br]]
 2) all the rest is True

 The bug can be traced to this code in forms.Form:
 {{{
 #!python
 def _get_changed_data(self):
     # ...
     for name, field in self.fields.items():
         # ...
         if field.widget._has_changed(initial_value, data_value):
             self._changed_data.append(name)
 }}}
 The initial_data here is taken from hidden_widget (which is filled with
 '0' for False when a form is first rendered) which is then casted to True
 by bool() inside CheckboxInput._has_changed.
 Therefore, the two possible fixes could be:[[br]]
 1) make CheckboxInput._has_changed smarter and treat initial='0' as
 False[[br]]
 2) add a custom BooleanField.hidden_widget (so called BooleanHiddenInput)
 which would store !'' for False instead of '0'

 I prefer the second approach as it allows to get rid of hard coded
 comparisons against string '0'.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/11303#comment:10>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to