Opened 5 years ago

Closed 4 years ago

#17981 closed Bug (duplicate)

attr property unexpectedly shared between widgets in MultiWidget

Reported by: supervacuo 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


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 = (
    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 Changed 4 years ago by Koen Biermans

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset

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?

comment:2 Changed 4 years ago by Jannis Leidel

Resolution: duplicate
Status: newclosed

Yeah, this is just a duplicate of #5851.

Note: See TracTickets for help on using tickets.
Back to Top