From ac3aaaa740dcf9c6efd2f88ee9219c1924c7695e Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Thu, 21 Jul 2016 17:16:22 -0700 Subject: [PATCH] Fixed #26927 -- Made subwidget iteration pass disabled and required attributes. --- django/forms/boundfield.py | 16 ++++++++--- django/forms/widgets.py | 7 +++++ docs/ref/forms/widgets.txt | 6 +++-- tests/forms_tests/tests/test_forms.py | 38 +++++++++++++-------------- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py index 4867e72deb..df3de5848e 100644 --- a/django/forms/boundfield.py +++ b/django/forms/boundfield.py @@ -51,6 +51,7 @@ class BoundField(object): """ id_ = self.field.widget.attrs.get('id') or self.auto_id attrs = {'id': id_} if id_ else {} + attrs = self.build_widget_attrs(attrs) for subwidget in self.field.widget.subwidgets(self.html_name, self.value(), attrs): yield subwidget @@ -85,10 +86,7 @@ class BoundField(object): widget.is_localized = True attrs = attrs or {} - if not widget.is_hidden and self.field.required and self.form.use_required_attribute: - attrs['required'] = True - if self.field.disabled: - attrs['disabled'] = True + attrs = self.build_widget_attrs(attrs, widget) auto_id = self.auto_id if auto_id and 'id' not in attrs and 'id' not in widget.attrs: if not only_initial: @@ -227,3 +225,13 @@ class BoundField(object): widget = self.field.widget id_ = widget.attrs.get('id') or self.auto_id return widget.id_for_label(id_) + + def build_widget_attrs(self, attrs, widget=None): + if not widget: + widget = self.field.widget + attrs = dict(attrs) # Copy attrs to avoid modifying the argument. + if not widget.is_hidden and self.field.required and self.form.use_required_attribute: + attrs['required'] = True + if self.field.disabled: + attrs['disabled'] = True + return attrs diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 604a6a401a..217f37b022 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -787,6 +787,13 @@ class CheckboxSelectMultiple(RendererMixin, SelectMultiple): renderer = CheckboxFieldRenderer _empty_value = [] + def build_attrs(self, extra_attrs=None, **kwargs): + attrs = super(CheckboxSelectMultiple, self).build_attrs(extra_attrs, **kwargs) + # Remove the 'required' attribute because browser validation would + # require all checkboxes to be checked instead of at least one. + attrs.pop('required', None) + return attrs + class MultiWidget(Widget): """ diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index 6a8cdf3c70..aae92a37c9 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -714,8 +714,10 @@ Selector and checkbox widgets The outer ``