diff options
| author | sanjeevholla26 <sanjeevholla26@gmail.com> | 2024-08-30 23:44:32 +0530 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-09-02 15:19:33 +0200 |
| commit | 387475c5b2f1aa32103dbe21cb281d3b35165a0c (patch) | |
| tree | c239d02a75de21531ef368e08e68ae05f68ac75a | |
| parent | e4a2e22ddbf1b892144b35dc21404c164bc848c6 (diff) | |
Refs #35706 -- Prefixed 'Error:' to titles of admin pages with form errors.
This improves the screen reader experience.
10 files changed, 63 insertions, 0 deletions
diff --git a/django/contrib/admin/templates/admin/auth/user/change_password.html b/django/contrib/admin/templates/admin/auth/user/change_password.html index 6801fe5fa7..c9a494dc19 100644 --- a/django/contrib/admin/templates/admin/auth/user/change_password.html +++ b/django/contrib/admin/templates/admin/auth/user/change_password.html @@ -2,6 +2,7 @@ {% load i18n static %} {% load admin_urls %} +{% block title %}{% if form.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %} {{ block.super }} <link rel="stylesheet" href="{% static "admin/css/forms.css" %}"> diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index 09ef954e5c..b9bde30018 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -1,6 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n admin_urls static admin_modify %} +{% block title %}{% if errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrahead %}{{ block.super }} <script src="{% url 'admin:jsi18n' %}"></script> {{ media }} diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html index 310872b015..fa189102bb 100644 --- a/django/contrib/admin/templates/admin/change_list.html +++ b/django/contrib/admin/templates/admin/change_list.html @@ -1,6 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n admin_urls static admin_list %} +{% block title %}{% if cl.formset and cl.formset.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %} {{ block.super }} <link rel="stylesheet" href="{% static "admin/css/changelists.css" %}"> diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html index b61d9ec603..8c2c7d11ff 100644 --- a/django/contrib/admin/templates/admin/login.html +++ b/django/contrib/admin/templates/admin/login.html @@ -1,6 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n static %} +{% block title %}{% if form.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/login.css" %}"> {{ form.media }} {% endblock %} diff --git a/django/contrib/admin/templates/registration/password_change_form.html b/django/contrib/admin/templates/registration/password_change_form.html index fde2373e08..20c78210c6 100644 --- a/django/contrib/admin/templates/registration/password_change_form.html +++ b/django/contrib/admin/templates/registration/password_change_form.html @@ -1,5 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n static %} + +{% block title %}{% if form.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %} {% block userlinks %} {% url 'django-admindocs-docroot' as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% translate 'Documentation' %}</a> / {% endif %} {% translate 'Change password' %} / diff --git a/django/contrib/admin/templates/registration/password_reset_confirm.html b/django/contrib/admin/templates/registration/password_reset_confirm.html index a07645c97a..3866b5aead 100644 --- a/django/contrib/admin/templates/registration/password_reset_confirm.html +++ b/django/contrib/admin/templates/registration/password_reset_confirm.html @@ -1,6 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n static %} +{% block title %}{% if form.new_password1.errors or form.new_password2.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %} {% block breadcrumbs %} <div class="breadcrumbs"> diff --git a/django/contrib/admin/templates/registration/password_reset_form.html b/django/contrib/admin/templates/registration/password_reset_form.html index 0edfea8ec2..7200e0f8be 100644 --- a/django/contrib/admin/templates/registration/password_reset_form.html +++ b/django/contrib/admin/templates/registration/password_reset_form.html @@ -1,6 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n static %} +{% block title %}{% if form.email.errors %}{{ _('Error:') }} {% endif %}{{ block.super }}{% endblock %} {% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %} {% block breadcrumbs %} <div class="breadcrumbs"> diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index ec6820c62f..694f807781 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -1264,6 +1264,24 @@ class ChangeListTests(TestCase): # Check only the first few characters since the UUID may have dashes. self.assertIn(str(a.pk)[:8], context.captured_queries[4]["sql"]) + def test_list_editable_error_title(self): + a = Swallow.objects.create(origin="Swallow A", load=4, speed=1) + Swallow.objects.create(origin="Swallow B", load=2, speed=2) + data = { + "form-TOTAL_FORMS": "2", + "form-INITIAL_FORMS": "2", + "form-MIN_NUM_FORMS": "0", + "form-MAX_NUM_FORMS": "1000", + "form-0-uuid": str(a.pk), + "form-0-load": "invalid", + "_save": "Save", + } + superuser = self._create_superuser("superuser") + self.client.force_login(superuser) + changelist_url = reverse("admin:admin_changelist_swallow_changelist") + response = self.client.post(changelist_url, data=data) + self.assertContains(response, "Error: Select swallow to change") + def test_deterministic_order_for_unordered_model(self): """ The primary key is used in the ordering of the changelist's results to diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 9a031a1e51..fc1bb86d85 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -1508,6 +1508,24 @@ class AdminViewBasicTest(AdminViewBasicTestCase): self.assertContains(response, "<h1>Change article</h1>") self.assertContains(response, "<h2>Article 2</h2>") + def test_error_in_titles(self): + for url, subtitle in [ + ( + reverse("admin:admin_views_article_change", args=(self.a1.pk,)), + "Article 1 | Change article", + ), + (reverse("admin:admin_views_article_add"), "Add article"), + (reverse("admin:login"), "Log in"), + (reverse("admin:password_change"), "Password change"), + ( + reverse("admin:auth_user_password_change", args=(self.superuser.id,)), + "Change password: super", + ), + ]: + with self.subTest(url=url, subtitle=subtitle): + response = self.client.post(url, {}) + self.assertContains(response, f"<title>Error: {subtitle}") + def test_view_subtitle_per_object(self): viewuser = User.objects.create_user( username="viewuser", diff --git a/tests/auth_tests/test_templates.py b/tests/auth_tests/test_templates.py index ceecfa3325..edde6ca6b4 100644 --- a/tests/auth_tests/test_templates.py +++ b/tests/auth_tests/test_templates.py @@ -37,6 +37,12 @@ class AuthTemplateTests(TestCase): ) self.assertContains(response, "<h1>Password reset</h1>") + def test_password_reset_view_error_title(self): + response = self.client.post(reverse("password_reset"), {}) + self.assertContains( + response, "<title>Error: Password reset | Django site admin</title>" + ) + def test_password_reset_done_view(self): response = PasswordResetDoneView.as_view()(self.request) self.assertContains( @@ -77,6 +83,19 @@ class AuthTemplateTests(TestCase): '<input class="hidden" autocomplete="username" value="jsmith">', ) + def test_password_reset_confirm_view_error_title(self): + client = PasswordResetConfirmClient() + default_token_generator = PasswordResetTokenGenerator() + token = default_token_generator.make_token(self.user) + uidb64 = urlsafe_base64_encode(str(self.user.pk).encode()) + url = reverse( + "password_reset_confirm", kwargs={"uidb64": uidb64, "token": token} + ) + response = client.post(url, {}) + self.assertContains( + response, "<title>Error: Enter new password | Django site admin</title>" + ) + @override_settings(AUTH_USER_MODEL="auth_tests.CustomUser") def test_password_reset_confirm_view_custom_username_hint(self): custom_user = CustomUser.custom_objects.create_user( |
