diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
index 51450d1d9e..c1e57f8637 100644
--- a/django/contrib/admin/helpers.py
+++ b/django/contrib/admin/helpers.py
@@ -173,6 +173,7 @@ class AdminField:
self.is_first = is_first # Whether this field is first on the line
self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
self.is_readonly = False
+ self.is_fieldset = self.field.field.widget.use_fieldset
def label_tag(self):
classes = []
@@ -185,12 +186,14 @@ class AdminField:
if not self.is_first:
classes.append("inline")
attrs = {"class": " ".join(classes)} if classes else {}
+ tag = "legend" if self.is_fieldset else None
# checkboxes should not have a label suffix as the checkbox appears
# to the left of the label.
return self.field.label_tag(
contents=mark_safe(contents),
attrs=attrs,
label_suffix="" if self.is_checkbox else None,
+ tag=tag,
)
def errors(self):
diff --git a/django/contrib/admin/templates/admin/includes/fieldset.html b/django/contrib/admin/templates/admin/includes/fieldset.html
index 9c9b31965a..9cd8cc6a68 100644
--- a/django/contrib/admin/templates/admin/includes/fieldset.html
+++ b/django/contrib/admin/templates/admin/includes/fieldset.html
@@ -12,6 +12,7 @@
{% if line.fields|length == 1 %}{{ line.errors }}{% else %}
{% endif %}
{% for field in line %}
+ {% if field.is_fieldset %}{% endif %}
{% endfor %}
{% if not line.fields|length == 1 %}
{% endif %}
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 67742470bf..bf756d00a6 100644
--- a/django/contrib/admin/widgets.py
+++ b/django/contrib/admin/widgets.py
@@ -27,8 +27,6 @@ class FilteredSelectMultiple(forms.SelectMultiple):
catalog has been loaded in the page
"""
- use_fieldset = True
-
class Media:
js = [
"admin/js/core.js",
@@ -52,7 +50,6 @@ class FilteredSelectMultiple(forms.SelectMultiple):
class BaseAdminDateWidget(forms.DateInput):
- use_fieldset = True
class Media:
js = [
@@ -70,7 +67,6 @@ class AdminDateWidget(BaseAdminDateWidget):
class BaseAdminTimeWidget(forms.TimeInput):
- use_fieldset = True
class Media:
js = [
@@ -92,7 +88,6 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
A SplitDateTime Widget that has some admin-specific styling.
"""
- use_fieldset = True
template_name = "admin/widgets/split_datetime.html"
def __init__(self, attrs=None):
@@ -109,12 +104,10 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
class AdminRadioSelect(forms.RadioSelect):
- use_fieldset = True
template_name = "admin/widgets/radio.html"
class AdminFileWidget(forms.ClearableFileInput):
- use_fieldset = True
template_name = "admin/widgets/clearable_file_input.html"
@@ -144,7 +137,6 @@ class ForeignKeyRawIdWidget(forms.TextInput):
in a