Django Rest Framework Password Rest Confirm Email not showing Form and returning as none
Question:
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.
Answers:
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.
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.