fredley
fredley

Reputation: 33911

Show message after password change?

I'm using the default change password mechanism provided by django.

I'm using post_change_redirect to have the submitted form go straight back to my settings page, however I'd like to show a message to reassure the user that the operation has been successful. How can I detect whether I'm arriving in my settings view as the result of a successful password change, and add a message to that effect?

Upvotes: 5

Views: 7188

Answers (2)

Flux
Flux

Reputation: 10930

You can subclass django.contrib.auth.views.PasswordChangeView to add a message using the Django messages framework when the user successfully changes their password.

In views.py:

from django.contrib import messages
from django.contrib.auth.views import PasswordChangeView
from django.urls import reverse_lazy


class CustomPasswordChangeView(PasswordChangeView):
    # Optional (default: 'registration/password_change_form.html')
    template_name = 'myapp/my_password_change_form.html'
    # Optional (default: `reverse_lazy('password_change_done')`)
    success_url = reverse_lazy('settings')

    def form_valid(self, form):
        messages.success(self.request, 'Your password has been changed.')
        return super().form_valid(form)

Then in your app's urls.py:

from django.conf.urls import url
import myapp.views as views

urlpatterns = [
    url(r'^settings/password/change/$',
        views.CustomPasswordChangeView.as_view(),
        name='password_change'),
    # ...
]

This answer improves upon the one provided by @enginoid in these ways:

  • The form behaves nearly identically to the default password change mechanism.
  • Less code repetition.

Upvotes: 3

enginoid
enginoid

Reputation: 83

I wouldn't recommend checking in the settings view whether a user has arrived via a password change. I think that ideally, all of the logic for password changes is contained in the same place. This makes it easier to find the logic, and doesn't require the settings view to know about the password change view (so you could easily change the logic to redirect the user somewhere else).

Your best bet is to write your own view based on PasswordChangeForm instead of using the built-in password_change view. With this approach, you can use the message framework to display a success message. (You'll also have to enable the message framework and put its markup in your views.)

For example, if you wanted to display a simple message and redirect back to your URL pattern named 'settings', you could write a view such as this one:

from django.contrib import messages
from django.contrib.auth.forms import PasswordChangeForm
from django.core.urlresolvers import reverse_lazy
from django.views.generic import FormView


class PasswordChangeView(FormView):
    template_name = 'registration/password_change_form.html'
    form_class = PasswordChangeForm
    success_url = reverse_lazy('settings')

    def get_form_kwargs(self):
        kwargs = super(PasswordChangeView, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def form_valid(self, form):
        form.save()
        messages.success(self.request, "Your password has been changed.")
        return super(FormView, self).form_valid(form)

Hopefully, the password_change view will be made class-based in the future, allowing the same behavior with even less boilerplate.

Upvotes: 7

Related Questions