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.
Most probably the form
is not going to password_reset_confirm.html
since django-rest-framework 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.