I am attempting to do a password reset using Django using custom html templates. I am able to request an password reset by email (using the EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'), and I then get an "email" in the console, as I would like. The email does lead me to the "password_reset_confirm.html" page as I would like, and I can input the new passwords for the user associated with the user.
However I am getting the following error when I click the "Reset password!" button:
"Reverse for 'password_reset_complete' not found. 'password_reset_complete' is not a valid view function or pattern name."
Despite this error, the password does actually change, however I (obviously) do not want this error.
The structure of the project has a users "app" within the main structure, so it is:
project
main_app
users
----templates
--------registration
------------password_reset_form.html
------------password_reset_confirm.html
------------password_reset_done.html
------------password_reset_email.html
------------password_reset_complete.html
My code for urls.py in users is as follows:
from django.urls import path, include, reverse_lazy
from . import views
from django.contrib.auth import views as auth_views
app_name = 'users'
urlpatterns = [
# Default authorisation urls.
path('', include('django.contrib.auth.urls')),
# Registration page.
path('register/', views.register, name='register'),
# Password reset urls.
path(
'password_reset',
auth_views.PasswordResetView.as_view(
template_name='registration/password_reset_form.html',
email_template_name='registration/password_reset_email.html',
success_url=reverse_lazy('users:password_reset_done')
),
name='password_reset'
),
path(
'password_reset/done/',
auth_views.PasswordResetDoneView.as_view(template_name='registration/password_reset_done.html'),
name='password_reset_done'
),
path(
'reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='registration/password_reset_confirm.html',
success_url=reverse_lazy('users:password_reset_complete.html')
),
name='password_reset_confirm'
),
path(
'reset/done/',
auth_views.PasswordResetCompleteView.as_view(template_name='registration/password_reset_complete.html'),
name='password_reset_complete'
),
]
I had a similar issue but with "password_reset_done", however I was able to resolve this thanks to looking through this site, by adding
success_url=reverse_lazy('users:password_reset_done')
to the path for the password reset, and that resolved that issue, however I then bumped into a subsequent issue as above, and I haven't found any solutions that have resolved it. Adding the following to the path for the password_reset_confirmation didn't help:
success_url=reverse_lazy('users:password_reset_complete.html')
I tried changing this to a login page, for example, which appeared to change nothing, and on investigation found that I could remove the following and the program would be unaltered:
path(
'reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='registration/password_reset_confirm.html',
success_url=reverse_lazy('users:password_reset_complete.html')
),
name='password_reset_confirm'
),
path(
'reset/done/',
auth_views.PasswordResetCompleteView.as_view(template_name='registration/password_reset_complete.html'),
name='password_reset_complete'
),
Which is why the success_url in this case isn't changing the behaviour. I'm wondering if the password_reset_email.html is the culprit, in case this is resulting in "password_reset_confirm" being called, as opposed to "user:password_reset_confirm" (because the urlpattern is being ignored).
password_reset_email.html:
{% autoescape off %}
To initiate the password reset process for your account, click the link below:
{{ protocol }}://{{ domain }}{% url 'users:password_reset_confirm' uidb64=uid token=token %}
If clicking the link above doesn't, please copy and paste it into a new browser instead.
{% endautoescape %}
I have also included the password_reset_confirm.html code in case it helps:
{% extends "demeter_app/base.html" %}
{% block content %}
<p>Please enter your new password:</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Reset password!">
</form>
{% endblock content %}
Does anyone have any ideas as to how I can solve this? I've tried looking on Stackoverflow however most queries relate to password_reset_done and not password_reset_complete.
More of the error is below:
Environment:
Request Method: POST
Request URL: http://localhost:8000/users/reset/MQ/set-password/
Django Version: 3.1.7
Python Version: 3.9.2
Installed Applications:
['demeter_app',
'users',
'import_export',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\decorators\debug.py", line 89, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\decorators\cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\contrib\auth\views.py", line 272, in dispatch
return super().dispatch(*args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\contrib\auth\views.py", line 305, in form_valid
return super().form_valid(form)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\generic\edit.py", line 57, in form_valid
return HttpResponseRedirect(self.get_success_url())
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\views\generic\edit.py", line 51, in get_success_url
if not self.success_url:
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\utils\functional.py", line 135, in __wrapper__
res = func(*self.__args, **self.__kw)
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\urls\base.py", line 87, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "C:\Users\marcj\Documents\demeter\demeter_env\lib\site-packages\django\urls\resolvers.py", line 685, in _reverse_with_prefix
raise NoReverseMatch(msg)
Exception Type: NoReverseMatch at /users/reset/MQ/set-password/
Exception Value: Reverse for 'password_reset_complete' not found. 'password_reset_complete' is not a valid view function or pattern name.
Please let me know if there is anything else I can provide to help.