Search code examples
pythondjangodjango-templatesdjango-urlsdjango-authentication

How to pass change_password.html to replace Django Admin Password Reset


Currently in my urls.py I have the following links for user to reset their password

app_name = 'users'

urlpatterns = [
    path('password/', user_views.change_password, name='change_password'),
    path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', success_url=reverse_lazy('users:password_reset_done')), name='password_reset'),
    path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'),name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',auth_views.PasswordResetConfirmView.as_view(template_name='users/change_password.html',success_url=reverse_lazy('users:password_reset_complete')),name='password_reset_confirm'),
    path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'),name='password_reset_complete'),
]

here is the change_password.html

        <main class="mt-5" >
            <div class="container dark-grey-text mt-5">
                <div class="content-section">
                    <form method="POST">
                        {% csrf_token %}
                        <fieldset class="form-group">
                            <legend class="border-bottom mb-4">Reset Password</legend>
                            {{ form|crispy }}
                        </fieldset>
                        <div class="form-group">
                            <button class="btn btn-outline-info" type="submit">Reset Password</button>
                        </div>
                    </form>
                </div>
            </div>
        </main>

After the user receives the reset email and clicks on the link to reset password it goes to the Django Admin Style page to reset password.

How can I pass the template that I have change_password.html and how can I redirect afterwards to the login page to login?

Just to add more context not sure if it might be the reason in the main urls.py

urlpatterns = [
    path('', include('django.contrib.auth.urls')),
    path('admin/', admin.site.urls),
    path('users/', include('users.urls'), ),
]

Here is the terminal showing the sequence:

"GET /users/password-reset/ HTTP/1.1" 200 1849
"POST /users/password-reset/ HTTP/1.1" 302 0
"GET /users/password-reset/done/ HTTP/1.1" 200 1339
"GET /reset/NTM/xxxxxxxxxxxxxxxxx/ HTTP/1.1" 302 0
"GET /reset/NTM/set-password/ HTTP/1.1" 200 2288
"POST /reset/NTM/set-password/ HTTP/1.1" 302 0
"GET /reset/done/ HTTP/1.1" 200 1459

Solution

  • You can use PasswordResetConfirmView and then pass the template_name parameter.

    To redirect the user to the login page after resetting their password, you can set the login_url attribute to the URL of your login page.

    urls.py

    from django.contrib.auth import views as auth_views
    from users import views as user_views
    
    app_name = 'users'
    ..............
        path('login/', MyLoginView.as_view(redirect_authenticated_user=True, template_name='users/login.html'), name='login'),
        path('password/', user_views.change_password, name='change_password'),
        path('password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='users/change_password.html'), name='password_reset_confirm'),
        path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html', login_url='/any-login-url/'), name='password_reset_complete'),
        .............................
        ...............................
    

    Edit

    Try to create a subclass of PasswordResetConfirmView so:

    # in views.py
    
    from django.contrib.auth.views import PasswordResetConfirmView
    from django.urls import reverse_lazy
    
    class CustomPasswordResetConfirmView(PasswordResetConfirmView):
        template_name = 'users/change_password.html'
        post_reset_login = True
        success_url = reverse_lazy('any-login-url') 
    

    With the post_reset_login attribute set to True, the user will be automatically logged in after they reset their password, and they will be redirected to the URL specified in the success_url attribute.

    Then in urls.py:

    from .views import CustomPasswordResetConfirmView
    
    urlpatterns = [
        # ... 
        path('password-reset-confirm/<uidb64>/<token>/', CustomPasswordResetConfirmView.as_view(), name='password_reset_confirm'),
        # ...
    ]