New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed #34977: Make change password form reachable through button #17489
Conversation
I would go a different route to solve this issue, specially because I believe that the best practice for help texts is not to use markup at all (more so for easing translations). So my proposal is to:
This would also have the (nice) side effect to separate "form concerns" (ie help texts) from UI elements that want to be displayed together in a template. Initial proposal (to be discussed with the accessibility team): diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
index 5398af4dad..30d28cbe00 100644
--- a/django/contrib/auth/forms.py
+++ b/django/contrib/auth/forms.py
@@ -179,9 +179,8 @@ class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField(
label=_("Password"),
help_text=_(
- "<p>Raw passwords are not stored, so there is no way to see this "
- "user’s password, but you can change the password here:</p>"
- '<p><a class="button" role="button" href="{}">Change password</a></p>'
+ "Raw passwords are not stored, so there is no way to see this "
+ "user’s password."
),
)
diff --git a/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html b/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html
index c73042b18f..f88d2e1ba4 100644
--- a/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html
+++ b/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html
@@ -1,5 +1,8 @@
+{% load i18n %}
+
<div{% include 'django/forms/widgets/attrs.html' %}>
{% for entry in summary %}
<strong>{{ entry.label }}</strong>{% if entry.value %}: <bdi>{{ entry.value }}</bdi>{% endif %}
{% endfor %}
+<a class="button" role="button" href="../password/">{% trans "Change password" %}</a>
</div> |
Good idea! Once we're touching |
@fsbraun Would you have time to update this PR by rebasing onto main and ensuring is ready for re-review? Thanks! @django/accessibility Would you have any opinion on my proposal above? /remind me to re-check the status of this PR in 3 weeks |
@nessita set a reminder for 3/28/2024 |
52c7f22
to
64844a9
Compare
@nessita I've rebased and rewritten to reflect your first comment:
|
Thank you @fsbraun ! Please remember to update the ticket flags accordingly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good!
Added some comments, and also please note that this work needs documentation updates, specifically we should review if any of the existing docs mention the link, and also we need release notes in the 5.1.txt
file.
Thank you @fsbraun !
django/contrib/auth/forms.py
Outdated
@@ -54,11 +54,17 @@ def get_context(self, name, value, attrs): | |||
for key, value_ in hasher.safe_summary(value).items(): | |||
summary.append({"label": gettext(key), "value": value_}) | |||
context["summary"] = summary | |||
context["usable_password"] = len(summary) > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that is cleaner to define using value.startswith(UNUSABLE_PASSWORD_PREFIX)
. So, something like:
usable_password = not value.startswith(UNUSABLE_PASSWORD_PREFIX)
if not value or not usable_password:
summary.append({"label": gettext("No password set.")})
else:
# ...
context["usable_password"] = usable_password
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, since this is the Widget class, shall we instead add to the context the label and action of the button? My initial thinking is that approach would be cleaner and simpler in the template. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nessita What's the right way to get the admin namespace from within the widget? I would need it to reverse the set password URL. The template uses a ../bla
which indeed is a bit hacky. The reason might be that the admin namespace is not readily available.
Admin forms get the admin site passed to their __init__
function. But that pattern would require to change the signature of the UserChangeForm
which I would like to avoid.
I have moved the button label from the template to the get_context
method, however.
django/contrib/auth/forms.py
Outdated
css = { | ||
"all": ("admin/css/widgets.css",), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed? I have removed it and I still see the same formatting in the admin 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other widgets on the user change form load the widgets.css
, so removing it here will indeed not change anything.
I would still like to keep it, since the widget needs it for margins. If we removed the css from the widget it will fail to display properly if other widgets on the change from do not load the widgets.css
for whatever reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative: Have your own auth/css/widgets.css
? (Once might argue this is cleaner since it does not cross app boundaries.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the extra details. My advice then is as follows (I'll make a new commit with these):
- Change the HTML to make use of semantic elements such as
<p>
- Remove the new CSS classes and custom CSS rule
- Let users of this widget define their own CSS by including the widget in whichever CSS context is relevant for them.
@nessita Thank you for your comments! I added a bullet point to the release notes. I searched the docs and did not find a reference to the link. Have I missed something? I also implemented some of your comments where I did not see any roadblocks. I added comments to the others. Getting the URL of the change password action from within the widget seems tricky to me. |
Building docs fails apparently since it cannot locate the class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks! I will make a few tweaks and merge. 🏆
django/contrib/auth/forms.py
Outdated
css = { | ||
"all": ("admin/css/widgets.css",), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the extra details. My advice then is as follows (I'll make a new commit with these):
- Change the HTML to make use of semantic elements such as
<p>
- Remove the new CSS classes and custom CSS rule
- Let users of this widget define their own CSS by including the widget in whichever CSS context is relevant for them.
…cing the reset password link with a button. Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
https://code.djangoproject.com/ticket/34977
To improve usability and accessibility, this PR replaces the link to change a user's password within the help text of the password field of the change user form by a button.
Besides an improved user experience, I would expect this PR to also improve accessibility. But since I am anything but an expert on accessibility, I would like to ask the accessibility team to review and give hints on hot to improve accessibility.