Django Rest Framework Password Rest Confirm Email not showing Form and returning as none

215 Views Asked by At

In my Django Rest Framework, the users request to reset the password and when the email is received and the link is clicked, the url password-reset-confirm/<uidb64>/<token>/ as comes up requested but the form is not showing and when I added it as {{ form }} is displayed NONE

The password reset process is working perfectly fine when I do everytihng on the Django but if I try to reset the password from Django Rest Framework the form does not appear.

Here is the main urls.py

urlpatterns = [
    path('', include('django.contrib.auth.urls')),
    path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', success_url=reverse_lazy('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/password_reset_confirm.html'),name='password_reset_confirm',),
    path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'), name='password_reset_complete'),
    path('admin/', admin.site.urls),
    path('api/', include('api.urls'), ),
    path('users/', include('users.urls'), ),
]

Here is the API app urls.py that is related to DRF

app_name = 'api'

router = routers.DefaultRouter()
router.register(r'users', UserViewSet, basename='user')

urlpatterns = [
    path('', include(router.urls)),
    path('dj-rest-auth/', include('dj_rest_auth.urls')),
    path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
    path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

here is the template password_reset_confirm.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 }}
                            {{ form }}

                        </fieldset>
                        <div class="form-group">
                            <button class="btn btn-outline-info" type="submit">Reset Password</button>
                        </div>
                    </form>
                </div>
            </div>
        </main>

My question is: Why is the form showing as NONE and how do I fix it.

1

There are 1 best solutions below

1
Sunderam Dubey On BEST ANSWER

Most probably the form is not going to password_reset_confirm.html since does not include the form in the context of the PasswordResetConfirmView by default.

Currently, the thing you can do is to create a custom PasswordResetConfirmView by inheriting it in a sub class and pass the form to the template context, using form_class attribute so:

from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.views import PasswordResetConfirmView
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters


class CustomPasswordResetConfirmView(PasswordResetConfirmView):
    form_class = SetPasswordForm
    success_url = reverse_lazy('password_reset_complete')
    template_name = 'users/password_reset_confirm.html'

    @method_decorator(sensitive_post_parameters('new_password1', 'new_password2'))
    @method_decorator(csrf_protect)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = self.form_class(user=self.request.user)
        return context

Then in urls.py:

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

You can provide any success_url according to your need.