1
0
mirror of https://github.com/django/django.git synced 2024-12-22 09:05:43 +00:00

Fixed #34045 -- Improved accessibility of selecting items in admin changelist.

This adds "aria-label".
This commit is contained in:
Durval Carvalho 2023-01-31 15:05:03 -03:00 committed by Mariusz Felisiak
parent 6bdc3c58b6
commit 85366fbca7
7 changed files with 27 additions and 15 deletions

View File

@ -288,6 +288,7 @@ answer newbie questions, and generally made Django that much better:
Doug Beck <doug@douglasbeck.com> Doug Beck <doug@douglasbeck.com>
Doug Napoleone <doug@dougma.com> Doug Napoleone <doug@dougma.com>
dready <wil@mojipage.com> dready <wil@mojipage.com>
Durval Carvalho de Souza <dudurval2@gmail.com>
dusk@woofle.net dusk@woofle.net
Dustyn Gibson <miigotu@gmail.com> Dustyn Gibson <miigotu@gmail.com>
Ed Morley <https://github.com/edmorley> Ed Morley <https://github.com/edmorley>

View File

@ -36,9 +36,6 @@ class ActionForm(forms.Form):
) )
checkbox = forms.CheckboxInput({"class": "action-select"}, lambda value: False)
class AdminForm: class AdminForm:
def __init__( def __init__(
self, self,

View File

@ -13,7 +13,6 @@ from django.contrib.admin.checks import (
InlineModelAdminChecks, InlineModelAdminChecks,
ModelAdminChecks, ModelAdminChecks,
) )
from django.contrib.admin.decorators import display
from django.contrib.admin.exceptions import DisallowedModelAdminToField from django.contrib.admin.exceptions import DisallowedModelAdminToField
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib.admin.utils import ( from django.contrib.admin.utils import (
@ -962,12 +961,16 @@ class ModelAdmin(BaseModelAdmin):
action_flag=DELETION, action_flag=DELETION,
) )
@display(description=mark_safe('<input type="checkbox" id="action-toggle">'))
def action_checkbox(self, obj): def action_checkbox(self, obj):
""" """
A list_display column containing a checkbox widget. A list_display column containing a checkbox widget.
""" """
return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, str(obj.pk)) attrs = {
"class": "action-select",
"aria-label": format_html(_("Select this object for an action - {}"), obj),
}
checkbox = forms.CheckboxInput(attrs, lambda value: False)
return checkbox.render(helpers.ACTION_CHECKBOX_NAME, str(obj.pk))
@staticmethod @staticmethod
def _get_action_description(func, name): def _get_action_description(func, name):

View File

@ -96,8 +96,12 @@ def result_headers(cl):
# if the field is the action checkbox: no sorting and special class # if the field is the action checkbox: no sorting and special class
if field_name == "action_checkbox": if field_name == "action_checkbox":
aria_label = _("Select all objects on this page for an action")
yield { yield {
"text": text, "text": mark_safe(
f'<input type="checkbox" id="action-toggle" '
f'aria-label="{aria_label}">'
),
"class_attrib": mark_safe(' class="action-checkbox-column"'), "class_attrib": mark_safe(' class="action-checkbox-column"'),
"sortable": False, "sortable": False,
} }

View File

@ -254,6 +254,8 @@ Miscellaneous
* The ``instance`` argument of the undocumented * The ``instance`` argument of the undocumented
``BaseModelFormSet.save_existing()`` method is renamed to ``obj``. ``BaseModelFormSet.save_existing()`` method is renamed to ``obj``.
* The undocumented ``django.contrib.admin.helpers.checkbox`` is removed.
.. _deprecated-features-5.0: .. _deprecated-features-5.0:
Features deprecated in 5.0 Features deprecated in 5.0

View File

@ -17,7 +17,7 @@
<table id="result_list"> <table id="result_list">
<tr> <tr>
<th> <th>
<input type="checkbox" id="action-toggle"> <input type="checkbox" id="action-toggle" aria-label="Select all objects on this page for an action">
</th> </th>
</tr> </tr>
<tr> <tr>

View File

@ -74,15 +74,15 @@ from .models import (
) )
def build_tbody_html(pk, href, extra_fields): def build_tbody_html(obj, href, extra_fields):
return ( return (
"<tbody><tr>" "<tbody><tr>"
'<td class="action-checkbox">' '<td class="action-checkbox">'
'<input type="checkbox" name="_selected_action" value="{}" ' '<input type="checkbox" name="_selected_action" value="{}" '
'class="action-select"></td>' 'class="action-select" aria-label="Select this object for an action - {}"></td>'
'<th class="field-name"><a href="{}">name</a></th>' '<th class="field-name"><a href="{}">name</a></th>'
"{}</tr></tbody>" "{}</tr></tbody>"
).format(pk, href, extra_fields) ).format(obj.pk, str(obj), href, extra_fields)
@override_settings(ROOT_URLCONF="admin_changelist.urls") @override_settings(ROOT_URLCONF="admin_changelist.urls")
@ -245,7 +245,7 @@ class ChangeListTests(TestCase):
table_output = template.render(context) table_output = template.render(context)
link = reverse("admin:admin_changelist_child_change", args=(new_child.id,)) link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
row_html = build_tbody_html( row_html = build_tbody_html(
new_child.id, link, '<td class="field-parent nowrap">-</td>' new_child, link, '<td class="field-parent nowrap">-</td>'
) )
self.assertNotEqual( self.assertNotEqual(
table_output.find(row_html), table_output.find(row_html),
@ -272,7 +272,7 @@ class ChangeListTests(TestCase):
table_output = template.render(context) table_output = template.render(context)
link = reverse("admin:admin_changelist_child_change", args=(new_child.id,)) link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
row_html = build_tbody_html( row_html = build_tbody_html(
new_child.id, link, '<td class="field-parent nowrap">???</td>' new_child, link, '<td class="field-parent nowrap">???</td>'
) )
self.assertNotEqual( self.assertNotEqual(
table_output.find(row_html), table_output.find(row_html),
@ -297,7 +297,7 @@ class ChangeListTests(TestCase):
table_output = template.render(context) table_output = template.render(context)
link = reverse("admin:admin_changelist_child_change", args=(new_child.id,)) link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
row_html = build_tbody_html( row_html = build_tbody_html(
new_child.id, new_child,
link, link,
'<td class="field-age_display">&amp;dagger;</td>' '<td class="field-age_display">&amp;dagger;</td>'
'<td class="field-age">-empty-</td>', '<td class="field-age">-empty-</td>',
@ -327,13 +327,18 @@ class ChangeListTests(TestCase):
table_output = template.render(context) table_output = template.render(context)
link = reverse("admin:admin_changelist_child_change", args=(new_child.id,)) link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
row_html = build_tbody_html( row_html = build_tbody_html(
new_child.id, link, '<td class="field-parent nowrap">%s</td>' % new_parent new_child, link, '<td class="field-parent nowrap">%s</td>' % new_parent
) )
self.assertNotEqual( self.assertNotEqual(
table_output.find(row_html), table_output.find(row_html),
-1, -1,
"Failed to find expected row element: %s" % table_output, "Failed to find expected row element: %s" % table_output,
) )
self.assertInHTML(
'<input type="checkbox" id="action-toggle" '
'aria-label="Select all objects on this page for an action">',
table_output,
)
def test_result_list_editable_html(self): def test_result_list_editable_html(self):
""" """