diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py
index 3c27f7e2c1..585e12cc18 100644
--- a/django/newforms/widgets.py
+++ b/django/newforms/widgets.py
@@ -258,11 +258,16 @@ class RadioSelect(Select):
class CheckboxSelectMultiple(SelectMultiple):
def render(self, name, value, attrs=None, choices=()):
if value is None: value = []
+ has_id = attrs and attrs.has_key('id')
final_attrs = self.build_attrs(attrs, name=name)
output = [u'
']
str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
- cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
- for option_value, option_label in chain(self.choices, choices):
+ for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
+ # If an ID attribute was given, add a numeric index as a suffix,
+ # so that the checkboxes don't all have the same ID attribute.
+ if has_id:
+ final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
+ cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
option_value = smart_unicode(option_value)
rendered_cb = cb.render(name, option_value)
output.append(u'' % (rendered_cb, escape(smart_unicode(option_label))))
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index 328582d162..f60898c179 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -2149,6 +2149,16 @@ MultipleChoiceField can also be used with the CheckboxSelectMultiple widget.
+Regarding auto_id, CheckboxSelectMultiple is a special case. Each checkbox
+gets a distinct ID, formed by appending an underscore plus the checkbox's
+zero-based index.
+>>> f = SongForm(auto_id='%s_id')
+>>> print f['composers']
+
+
+
+
+
Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict
conveniently work with this.
>>> data = {'name': 'Yesterday', 'composers': ['J', 'P']}