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 %} {% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if field.is_checkbox %} @@ -30,6 +31,7 @@
{{ field.field.help_text|safe }}
{% endif %} + {% 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