How to reset user password from the admin interface

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.


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 :-).