Opened 13 years ago
Closed 12 years ago
#17981 closed Bug (duplicate)
attr property unexpectedly shared between widgets in MultiWidget
Reported by: | c v t | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
I have encountered the following method for making a widget that's just an existing widget with a custom class (from the django-bootstrap-toolkit project):
class FooWidget(forms.TextInput): def render(self, name, value, attrs=None): if not attrs: attrs = {} attrs['class'] = 'flibble' return super(FooWidget, self).render(name, value, attrs)
(code to only add class conditionally omitted for clarity).
I tried adding such a widget to another custom widget, based on MultiWidget
:
class BarWidget(forms.MultiWidget): def __init__(self): widgets = ( FooWidget(), forms.TextInput(),) super(BarWidget, self).__init__(widgets, None)
but in the output, both widgets are rendered with class = 'flibble'
. If the order of widgets
reversed, only FooWidget
has the applied class, as expected.
I can't see anything in the definition of MultiWidget
which immediately explains this. Thoughts?
This is not a duplicate of #5851 (as far as I can tell).
Change History (2)
comment:1 by , 13 years ago
comment:2 by , 12 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Yeah, this is just a duplicate of #5851.
This is actually a bug in your code, not in django's. You are modifying the attrs object in your render method. Remember that objects are passed into functions by reference in python, so if the multiwidget passes a dict into the render method, you are changing that dict inside your method, not a copy.
This is actually an easy mistake to make, so we may be able to protect against this in the multiwidget code. The patch I added to #5851 for instance does not have this problem anymore, since it passes a different dict into the different render methods.
Not sure whether I should leave this open?