Oscar Mederos
Oscar Mederos

Reputation: 29863

How to reset user password from the admin interface

In my website, I want to let the admins reset the password of any user.

With reset I mean exactly what the password_reset view does (under contrib.auth): Send a confirmation link to that user email.

How would be the best way of doing that? Is there an already app/snippet that does that?

Edit:

Let's suppose user john is an admin. What I want is to let john reset any user's password through the admin interface. For example, to reset max password, he will just go to the max user, and click on any link to reset his password.

Upvotes: 7

Views: 10472

Answers (3)

Oscar Mederos
Oscar Mederos

Reputation: 29863

What I finally did was to add a custom ModelAdmin:

from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.admin import UserAdmin


class CustomUserAdmin(UserAdmin):
    ...
    def reset_password(self, request, user_id):
        if not self.has_change_permission(request):
            raise PermissionDenied
        user = get_object_or_404(self.model, pk=user_id)

        form = PasswordResetForm(data={'email': user.email})
        form.is_valid()

        form.save(email_template_name='my_template.html')
        return HttpResponseRedirect('..')

    def get_urls(self):
        urls = super(UserAdmin, self).get_urls()

        my_urls = patterns('',
            (r'^(\d+)/reset-password/$',
                     self.admin_site.admin_view(self.reset_password)
            ),
        )
        return my_urls + urls

and I also had to override the change_form.html template, like this:

{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
    {% if change %}{% if not is_popup %}
        <ul class="object-tools">
            {# You can also give a name to that pattern and refer to it below using 'url' #}
            <li><a href="reset-password/" class="historylink">Reset password</a></li>

            <li><a href="history/" class="historylink">{% trans "History" %}</a></li>
            {% if has_absolute_url %}
                <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
                    {% trans "View on site" %}</a>
                </li>
            {% endif%}
        </ul>
    {% endif %}{% endif %}
{% endblock %}

The result looks like this:

Reset Password from admin in Django

If you want a more detailed explanation, I blogged about it.

Upvotes: 8

Danny W. Adair
Danny W. Adair

Reputation: 12978

The passreset app just exposes the django views via urls.py, and adjusts the login template to show a "Forgot my password" link.

The built-in django password reset views and templates are meant for self-reset. I guess the reset form could be prepopulated with a different user's email address (in the query string) but you'd still need to make adjustments such as changing the email template - "You're receiving this e-mail because you requested a password reset for your user account" is probably not what you want:

https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/registration/password_reset_email.html

Therefore you should expose the views at different URLs if you want to include self-reset as well. Hook the django views into urls.py like so:

urlpatterns += patterns('django.contrib.auth.views', 
    url(r'^accounts/password/reset/$',
        'password_reset',
        name='password-reset'), 
    url(r'^accounts/password/reset/done/$',
        'password_reset_done',
        name='password-reset-done'), 
    url(r'^accounts/password/reset/confirm/(?P<uidb36>[-\w]+)/(?P<token>[-\w]+)/$',
        'password_reset_confirm',
        name='password-reset-confirm'), 
    url(r'^accounts/password/reset/complete/$',
        'views.password_reset_complete',
        name='password-reset-complete')
)

and where you want to make adjustments, pass in e.g. your own email template:

url(r'^/accounts/password/reset/$',
    'password_reset',
    {'email_template_name': 'my_templates/password_reset_email.html'}
    name='password-reset'),

The "password_reset" view has more parameters you can tweak: https://docs.djangoproject.com/en/dev/topics/auth/#module-django.contrib.auth.views ("post_reset_redirect" comes to mind as another one for your purposes)

To show a corresponding link you'd either change the User admin (careful, already registered - unregister then register your own, subclassed plus additional link field) or the change_form template itself.

I'm unaware of an app that provides this out-of-the-box, so I upvoted the question :-).

Upvotes: 2

alexarsh
alexarsh

Reputation: 5391

Yep, there is an app for that. Check here:

https://github.com/bendavis78/django-passreset

Upvotes: 0

Related Questions