From 907ef9d0d157c47c66bf265dca93a0bee8664ea3 Mon Sep 17 00:00:00 2001 From: Matt Johnson Date: Tue, 4 Jun 2013 22:41:49 +0200 Subject: [PATCH] Fixed #20555 -- Make subwidget id attribute available In `BoundField.__iter__`, the widget's id attribute is now passed to each subwidget. A new id_for_label property was added to ChoiceInput. --- django/forms/forms.py | 4 +- django/forms/widgets.py | 15 +++--- docs/ref/forms/widgets.txt | 65 ++++++++++++++++--------- docs/releases/1.7.txt | 7 +++ tests/forms_tests/tests/test_widgets.py | 16 ++++++ 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/django/forms/forms.py b/django/forms/forms.py index c2b700ce77..ec51507981 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -434,7 +434,9 @@ class BoundField(object): This really is only useful for RadioSelect widgets, so that you can iterate over individual radio buttons in a template. """ - for subwidget in self.field.widget.subwidgets(self.html_name, self.value()): + id_ = self.field.widget.attrs.get('id') or self.auto_id + attrs = {'id': id_} if id_ else {} + for subwidget in self.field.widget.subwidgets(self.html_name, self.value(), attrs): yield subwidget def __len__(self): diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 0a5059a9c2..98d47d0b00 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -601,16 +601,15 @@ class ChoiceInput(SubWidget): self.choice_value = force_text(choice[0]) self.choice_label = force_text(choice[1]) self.index = index + if 'id' in self.attrs: + self.attrs['id'] += "_%d" % self.index def __str__(self): return self.render() def render(self, name=None, value=None, attrs=None, choices=()): - name = name or self.name - value = value or self.value - attrs = attrs or self.attrs - if 'id' in self.attrs: - label_for = format_html(' for="{0}_{1}"', self.attrs['id'], self.index) + if self.id_for_label: + label_for = format_html(' for="{0}"', self.id_for_label) else: label_for = '' return format_html('{1} {2}', label_for, self.tag(), self.choice_label) @@ -619,13 +618,15 @@ class ChoiceInput(SubWidget): return self.value == self.choice_value def tag(self): - if 'id' in self.attrs: - self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) final_attrs = dict(self.attrs, type=self.input_type, name=self.name, value=self.choice_value) if self.is_checked(): final_attrs['checked'] = 'checked' return format_html('', flatatt(final_attrs)) + @property + def id_for_label(self): + return self.attrs.get('id', '') + class RadioChoiceInput(ChoiceInput): input_type = 'radio' diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index 080d1fea86..951fbfa310 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -590,25 +590,26 @@ Selector and checkbox widgets .. code-block:: html
- +
- +
- +
- +
That included the ``