[Django] #37298: Admin radio_fields have an invalid aria-describedby attribute.

12 views
Skip to first unread message

Django

unread,
Aug 24, 2026, 4:49:05 PMAug 24
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-----------------------------+-----------------------------------------
Reporter: David Smith | Type: Bug
Status: new | Component: contrib.admin
Version: 6.1 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-----------------------------+-----------------------------------------
#35892 added support for Widget.use_fieldset in admin forms. Refs
4187da258fe212d494cb578a0bc2b52c4979ab95

An incorrect aria-describedby attribute is generated for `radio_fields`
with `help_text` and no reference is available for errors.

Given this form:

{{{#!python
class Colour(models.Model):
name = models.CharField(max_length=100, help_text='Enter your name')

COLOUR_CHOICES = [
('red', 'Red'),
('green', 'Green'),
('blue', 'Blue'),]

favourite_colour = models.CharField(
max_length=10,
choices=COLOUR_CHOICES,
help_text='Colour of the favourite colour',
)
}}}

... and model admin:

{{{#!python
class ColourAdmin(admin.ModelAdmin):
radio_fields = {"favourite_colour": admin.VERTICAL}
model = Colour
}}}

Adding a new Colour record in the admin with no inputs gives the following
HTML for the `favourite_colour` field.

Notice how the aria-describedby in the `<fieldset>` is `_helptext`. This
id does not exist, and also there is no reference to
"id_favourite_colour_error" to reference the error list.

{{{
<fieldset aria-describedby="_helptext">
<legend class="required">Favourite colour:</legend>
<div class="flex-container errors">
<div class="help">
<div>Colour of the favourite colour</div>
</div>

<ul class="errorlist" id="id_favourite_colour_error">
<li>This field is required.</li>
</ul>

<div id="id_favourite_colour" class="radiolist">
<div>
<label for="id_favourite_colour_0">
<input type="radio" name="favourite_colour"
value="red" class="radiolist" required="" aria-invalid="true"
id="id_favourite_colour_0" /> Red
</label>
</div>
<div>
<label for="id_favourite_colour_1">
<input type="radio" name="favourite_colour"
value="green" class="radiolist" required="" aria-invalid="true"
id="id_favourite_colour_1" /> Green
</label>
</div>
<div>
<label for="id_favourite_colour_2">
<input type="radio" name="favourite_colour"
value="blue" class="radiolist" required="" aria-invalid="true"
id="id_favourite_colour_2" /> Blue
</label>
</div>
</div>
</div>
</fieldset>
}}}

Contrast that to the name field where both the help_text and errors have a
valid aria-describedby references from the `<input>`.

Using aria-describedby from the field's boundfield (field.field in this
case) is where I'd be looking to fix the issue.

{{{#!diff

diff --git a/django/contrib/admin/templates/admin/includes/fieldset.html
b/django/contrib/admin/templates/admin/includes/fieldset.html
index 70c68655c5..4ef3d01589 100644
--- a/django/contrib/admin/templates/admin/includes/fieldset.html
+++ b/django/contrib/admin/templates/admin/includes/fieldset.html
@@ -10,7 +10,7 @@
{% for line in fieldset %}
<div class="form-row{% if not line.fields|length == 1 %} flex-
container form-multiline{% endif %}{% if not line.has_visible_field %}
hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{
field.field.name }}{% endif %}{% endfor %}">
{% for field in line %}
- {% if field.is_fieldset %}<fieldset{% if
field.field.help_text %} aria-describedby="{{ field.field.id_for_label
}}_helptext"{% endif %}>{{ field.label_tag }}{% endif %}
+ {% if field.is_fieldset %}<fieldset{% if
field.field.aria_describedby %} aria-describedby="{{
field.field.aria_describedby }}"{% endif %}>{{ field.label_tag }}{% endif
%}
<div class="flex-container{% if not field.is_readonly and
field.errors or line.fields|length == 1 and line.errors %} errors{% endif
%}{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %}
field-{{ field.field.name }}{% endif %}{% if field.field.is_hidden %}
hidden{% endif %}{% endif %}{% if field.is_checkbox %} checkbox-row{%
endif %}">
{% if field.is_checkbox %}
<div class="checkbox">
@@ -21,7 +21,7 @@
{% if not field.is_fieldset %}{{ field.label_tag
}}{% endif %}
{% endif %}
{% if field.field.help_text %}
- <div class="help{% if field.field.is_hidden %}
hidden{% endif %}"{% if field.field.id_for_label %} id="{{
field.field.id_for_label }}_helptext"{% endif %}>
+ <div class="help{% if field.field.is_hidden %}
hidden{% endif %}"{% if field.field.auto_id %} id="{{ field.field.auto_id
}}_helptext"{% endif %}>
<div>{{ field.field.help_text|safe }}</div>
</div>
{% endif %}
}}}


Then for tests I'd suggest looking at the test that was added for admin
fieldsets. Additional tests can be added to assert the correct aria-
describedby attribute for both help_text and errors is present.
https://github.com/django/django/blob/0b40210e4808937a7c0922e8b7502bff4752faa3/tests/admin_views/tests.py#L7365
--
Ticket URL: <https://code.djangoproject.com/ticket/37298>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 25, 2026, 1:16:38 AMAug 25
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-------------------------------+-----------------------------------------
Reporter: David Smith | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Changes (by Zubair Hassan):

* owner: (none) => Zubair Hassan
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/37298#comment:1>

Django

unread,
Aug 25, 2026, 6:31:10 PMAug 25
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-------------------------------+-----------------------------------------
Reporter: David Smith | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Changes (by Clifford Gama):

* stage: Unreviewed => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/37298#comment:2>

Django

unread,
Aug 26, 2026, 2:34:26 AMAug 26
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-------------------------------+-----------------------------------------
Reporter: David Smith | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Changes (by Zubair Hassan):

* has_patch: 0 => 1

Comment:

https://github.com/django/django/pull/21827
--
Ticket URL: <https://code.djangoproject.com/ticket/37298#comment:3>

Django

unread,
Aug 28, 2026, 4:31:00 PMAug 28
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-------------------------------------+-------------------------------------
Reporter: David Smith | Owner: Zubair
| Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Eric Sherman):

* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/37298#comment:4>

Django

unread,
9:48 AM (13 hours ago) 9:48 AM
to django-...@googlegroups.com
#37298: Admin radio_fields have an invalid aria-describedby attribute.
-------------------------------+-----------------------------------------
Reporter: David Smith | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Changes (by Sarah Boyce):

* needs_better_patch: 0 => 1
* stage: Ready for checkin => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/37298#comment:5>
Reply all
Reply to author
Forward
0 new messages