Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 665
fredley Avatar asked Nov 14 '12 16:11

fredley


2 Answers

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.

like image 135
enginoid Avatar answered Nov 03 '22 21:11

enginoid


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.
like image 38
Flux Avatar answered Nov 03 '22 22:11

Flux