#12048: MultiWidget does not define __deepcopy__
-------------------------------------------------+--------------------------
 Reporter:  powderflask <powderfl...@gmail.com>  |       Owner:  nobody    
   Status:  new                                  |   Milestone:  1.2       
Component:  Forms                                |     Version:  SVN       
 Keywords:                                       |       Stage:  Unreviewed
Has_patch:  1                                    |  
-------------------------------------------------+--------------------------
 django.forms.!MultiWidget defines an instance variable, {{{ widgets }}},
 which is a list of widgets.  However, it does not override the
 __deepcopy__() method in the Widget base class to make a copy of this
 instance variable.  A deepcopy of the widgets is needed when an instance
 when a django Form containing a Field that uses a !MultiWidget is
 instantiated, otherwise all such forms have a reference to the same
 widgets list rather than their own copy.

 The patch is simple - override __deepcopy__() in !MultiWidget to make a
 copy of widgets.  A proposed patch is attached.

 Replicating the problem requires that we extend !MultiWidget, make a
 deepcopy of the widget, then alter one of the widgets in some way.  Here
 is a minimal example that demonstrates the issue - applying the patch
 fixes the issue.

 {{{
 from django import forms
 from django.utils.encoding import StrAndUnicode, force_unicode
 from django.utils.safestring import mark_safe

 #####################################################
 ## Simplified ChoiceWithOtherWidget
 ##   original downloaded from: http://www.djangosnippets.org/snippets/863/
 #####################################################
 class ChoiceWithOtherWidget(forms.MultiWidget):
     """MultiWidget for use with ChoiceWithOtherField."""
     def __init__(self, choices=[]):
         widgets = [
             forms.RadioSelect(choices=choices),
             forms.TextInput
         ]
         super(ChoiceWithOtherWidget, self).__init__(widgets)

     def _set_choices(self, choices):
         """ When choices are set for this widget, we want to pass those
 along to the Select widget"""
         self.widgets[0].choices = choices
     def _get_choices(self):
         """ The choices for this widget are the Select widget's choices"""
         return self.widgets[0].choices
     choices = property(_get_choices, _set_choices)

     def decompress(self, value):
         if not value:
             return [None, None]
         return value


 #################################################
 ##  Minimal code to reproduces bug
 #################################################
 from copy import deepcopy

 widget1 = ChoiceWithOtherWidget(choices=['A','B','C'])
 widget2 = deepcopy(widget1)
 widget2.choices=['X','Y','Z']

 widget1.choices
 widget2.choices
 }}}

 Here is the output from running the sample code above in a shell before
 the patch was applied:
 {{{
 >>> widget1 = ChoiceWithOtherWidget(choices=['A','B','C'])
 >>> widget2 = deepcopy(widget1)
 >>> widget2.choices=['X','Y','Z']
 >>>
 >>> widget1.choices
 ['X', 'Y', 'Z']
 >>> widget2.choices
 ['X', 'Y', 'Z']
 }}}

 ... and after the patch was applied:

 {{{
 >>> widget1 = ChoiceWithOtherWidget(choices=['A','B','C'])
 >>> widget2 = deepcopy(widget1)
 >>> widget2.choices=['X','Y','Z']
 >>>
 >>> widget1.choices
 ['A', 'B', 'C']
 >>> widget2.choices
 ['X', 'Y', 'Z']
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/12048>
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-updates@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