Django密码重置出现NoReverseMatch错误求助
Django密码重置模块NoReverseMatch问题解决
我是一名Django新手,正在跟随书籍教程开发项目(项目有部分改动)。在实现登录/注册功能时,卡在了密码重置模块。我知道问题与命名空间相关,但无法确定具体原因及为何无法重定向到错误中提及的页面。
遇到的错误
错误1
NoReverseMatch at /password_reset/ Reverse for 'password_reset_done' not found. 'password_reset_done' is not a valid view function or pattern name.
错误2
NoReverseMatch at /reset/MQ/set-password/ Reverse for 'password_reset_complete' not found. 'password_reset_complete' is not a valid view function or pattern name.
项目代码文件
urls.py
from django.urls import path, include from . import views from .feeds import LatestLessonsFeed from django.contrib.auth import views as auth_views app_name = 'learning_app' urlpatterns = [ #lessons path('', views.lesson_list, name='lesson_list'), path('<int:year>/<int:month>/<int:day>/<slug:lesson>/', views.lesson_detail, name='lesson_detail'), #tags path('tag/<slug:tag_slug>/', views.lesson_list, name='lesson_list_by_tag'), #feed path('feed/', LatestLessonsFeed(), name='post_feed'), # previous login view # path('login/', views.user_login, name='login'), # login / logout urls #path('login/', auth_views.LoginView.as_view(), name='login'), #path('logout/', auth_views.LogoutView.as_view(), name='logout'), # change password urls #path('password-change/', auth_views.PasswordChangeView.as_view(), name='password_change'), #path('password-change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'), # reset password urls #path('password-reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), #path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'), #path('password-reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), #path('password-reset/complete/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'), #dashboard path('dashboard/', views.dashboard, name='dashboard'), #django auth path('', include('django.contrib.auth.urls')), ]
HTML模板文件
login.html
{% extends "base.html" %} {% block title %}Log-in{% endblock %} {% block content %} <h1>Log-in</h1> {% if form.errors %} <p>Your username and password didn't match. Please try again.</p> {% else %} <p>Please, use the following form to log-in:</p> {% endif %} <div class="login-form"> <form action="{% url 'learning_app:login' %}" method="post"> {{ form.as_p }} {% csrf_token %} <input type="hidden" name="next" value="{{ next }}" /> <p><input type="submit" value="Log-in"></p> </form> <p> <a href="{% url 'learning_app:password_reset' %}"> Forgotten your password? </a> </p> </div> {% endblock %}
password_reset_form.html
{% extends "base.html" %} {% block title %}Reset your password{% endblock %} {% block content %} <h1>Forgotten your password?</h1> <p>Enter your e-mail address to obtain a new password.</p> <form method="post" action="{% url 'learning_app:password_reset' %}"> {{ form.as_p }} <p><input type="submit" value="Send e-mail"></p> {% csrf_token %} </form> {% endblock %}
password_reset_email.html
Someone asked for password reset for email {{ email }}. Follow the link below: {{ protocol }}://{{ domain }}{% url "learning_app:password_reset_confirm" uidb64=uid token=token %} Your username, in case you've forgotten: {{ user.get_username }}
password_reset_done.html
{% extends "base.html" %} {% block title %}Reset your password{% endblock %} {% block content %} <h1>Reset your password</h1> <p>We've emailed you instructions for setting your password.</p> <p>If you don't receive an email, please make sure you've entered the address you registered with.</p> {% endblock %}
password_reset_confirm.html
{% extends "base.html" %} {% block title %}Reset your password{% endblock %} {% block content %} <h1>Reset your password</h1> {% if validlink %} <p>Please enter your new password twice:</p> <form method="post"> {{ form.as_p }} {% csrf_token %} <p><input type="submit" value="Change my password" /></p> </form> {% else %} <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p> {% endif %} {% endblock %}
问题原因及解决办法
核心问题
你把自定义的密码重置URL全部注释,转而使用include('django.contrib.auth.urls')引入官方认证URL,但你的模板中所有密码重置相关的URL调用都使用了learning_app:的命名空间前缀,而官方认证URL属于全局命名空间,不属于learning_app,导致Django无法找到对应命名空间下的URL,抛出NoReverseMatch错误。
解决办法(二选一)
办法一:启用自定义的密码重置URL(推荐,匹配你现有模板的命名空间调用)
打开urls.py,取消注释以下密码重置相关的URL配置:
# reset password urls path('password-reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'), path('password-reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), path('password-reset/complete/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
取消注释后,这些URL会注册到learning_app命名空间下,和你模板中{% url 'learning_app:password_reset' %}这类调用完全匹配,反向解析就能正常工作。
办法二:修改模板中的URL调用(适配官方认证URL的全局命名空间)
如果你想继续使用include('django.contrib.auth.urls'),需要把所有模板中的learning_app:前缀去掉:
- 比如
login.html中的{% url 'learning_app:password_reset' %}改成{% url 'password_reset' %} password_reset_form.html中的{% url 'learning_app:password_reset' %}改成{% url 'password_reset' %}password_reset_email.html中的{% url "learning_app:password_reset_confirm" ... %}改成{% url "password_reset_confirm" ... %}
这样模板就会去全局命名空间查找官方认证的URL,也能解决反向解析错误。
内容的提问来源于stack exchange,提问作者mdev
相关产品推荐
相关产品推荐

