#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 -~----------~----~----~----~------~----~------~--~---