diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py index e83160645e..9f2ae59ab4 100644 --- a/django/forms/boundfield.py +++ b/django/forms/boundfield.py @@ -286,6 +286,13 @@ class BoundField: r"widget$|input$", "", self.field.widget.__class__.__name__.lower() ) + @property + def use_fieldset(self): + """ + Return the value of this BoundField widget's use_fieldset attribute. + """ + return self.field.widget.use_fieldset + @html_safe class BoundWidget: diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 208464b60a..760579ebe5 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -234,6 +234,7 @@ class Widget(metaclass=MediaDefiningClass): is_localized = False is_required = False supports_microseconds = True + use_fieldset = False def __init__(self, attrs=None): self.attrs = {} if attrs is None else attrs.copy() @@ -821,6 +822,7 @@ class RadioSelect(ChoiceWidget): input_type = "radio" template_name = "django/forms/widgets/radio.html" option_template_name = "django/forms/widgets/radio_option.html" + use_fieldset = True def id_for_label(self, id_, index=None): """ @@ -862,6 +864,7 @@ class MultiWidget(Widget): """ template_name = "django/forms/widgets/multiwidget.html" + use_fieldset = True def __init__(self, widgets, attrs=None): if isinstance(widgets, dict): @@ -1027,6 +1030,7 @@ class SelectDateWidget(Widget): input_type = "select" select_widget = Select date_re = _lazy_re_compile(r"(\d{4}|0)-(\d\d?)-(\d\d?)$") + use_fieldset = True def __init__(self, attrs=None, years=None, months=None, empty_label=None): self.attrs = attrs or {} diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index e092a2f59e..4d3cf8997d 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -1160,6 +1160,12 @@ Attributes of ``BoundField`` >>> print(f['message'].name) message +.. attribute:: BoundField.use_fieldset + + .. versionadded:: 4.1 + + Returns the value of this BoundField widget's ``use_fieldset`` attribute. + .. attribute:: BoundField.widget_type Returns the lowercased class name of the wrapped field's widget, with any diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index 970e30456c..e0f175af79 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -315,6 +315,19 @@ foundation for custom widgets. ```` tags such as + :class:`~django.forms.CheckboxSelectMultiple`, + :class:`~django.forms.RadioSelect`, + :class:`~django.forms.MultiWidget`, + :class:`~django.forms.SplitDateTimeWidget`, and + :class:`~django.forms.SelectDateWidget`. + .. method:: use_required_attribute(initial) Given a form field's ``initial`` value, returns whether or not the diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt index 8fc81e5ee7..7660780ae5 100644 --- a/docs/releases/4.1.txt +++ b/docs/releases/4.1.txt @@ -217,6 +217,10 @@ Forms objects implement the ``__html__()`` method (typically when decorated with the :func:`~django.utils.html.html_safe` decorator). +* The new :attr:`.BoundField.use_fieldset` and :attr:`.Widget.use_fieldset` + attributes help to identify widgets where its inputs should be grouped in a + ``
`` with a ````. + Generic Views ~~~~~~~~~~~~~ diff --git a/docs/topics/forms/index.txt b/docs/topics/forms/index.txt index d87b9be8d6..2d0d61aa02 100644 --- a/docs/topics/forms/index.txt +++ b/docs/topics/forms/index.txt @@ -686,6 +686,32 @@ Useful attributes on ``{{ field }}`` include: +``{{ field.legend_tag }}`` + + .. versionadded:: 4.1 + + Similar to ``field.label_tag`` but uses a ```` tag in place of + ``