对 'password_change_done' 进行反转,其中未找到参数“()”和关键字参数“{}”

Reverse for 'password_change_done' with arguments '()' and keyword arguments '{}' not found

背景

我正在尝试在 Django 项目中自定义身份验证视图,但我似乎无法将自定义的 password_change 视图设置为 运行。我使用 Django 1.8.2 和 Python 2.7.

我的模块 userauthurls.py 如下所示:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('django.contrib.auth.views',
    url(r'^login/$', 'login', {'template_name': 'userauth/login.html'},
        name='userauth_login'),
    url(r'^logout/$', 'logout', {'next_page': '/'},
        name='userauth_logout'),
    url(r'^password-change/$', 'password_change',
        {'template_name': 'userauth/password_change_form.html'},
        name='userauth_password_change'),
    url(r'^password-change-done/$', 'password_change_done',
        {'template_name': 'userauth/password_change_done.html'},
        name='userauth_password_change_done'),
)

这在主要 urls.py 中被引用为:

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^account/', include('userauth.urls')),
]

我的模板userauth/password_change_form.html

{% extends "base.html" %}

{% block title %}{{ block.super }} - Change Password{% endblock %}

{% block toggle_login %}{% endblock %}

{% block content %}
<form action="{% url 'userauth_password_change' %}" method="post" accept-charset="utf-8">
  {{ form.as_p }}
  {% csrf_token %}
  <input type="submit" value="Change password"/>
</form>
{% endblock %}

以及 userauth/password_change_done.html

的模板
{% extends "base.html" %}

{% block title %}{{ block.super }} - Password change successful{% endblock %}

{% block content %}
<p>Your password has been changed successfully.</p>
<a href="{% url 'products_product_index' %}">Back to your Account</a>
{% endblock %}

问题

当我打开 'password_change_done' 页面(在 /account/password-change-done)时,一切正常。

但是在 'password-change' (/accunt/password-change) 我收到这个错误:

NoReverseMatch at /account/password-change/

Reverse for 'password_change_done' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []

我试过的

我不知道为什么会这样。

  1. 我尝试从 url 'userauth_password_change'
  2. 中删除单引号
  3. 我确保 password-change-done 页面存在于 urls.py 中并且可用
  4. 我在 Reverse for '*' with arguments '()' and keyword arguments '{}' not found, Django: Reverse for 'detail' with arguments '('',)' and keyword arguments '{}' not found, Django change_password NoReverseMatch at /accounts/password/change/ 阅读了解决方案(还有一些,我尝试了那里的所有解决方案,但我在自己的代码中找不到问题)

感谢任何帮助。谢谢!

在某些部分中,您将 url 命名为 "password_change_done"

正确的名字是:"userauth_password_change_done"

解决方案是,在 urls.py 中 password_change_done link 的名称必须 'password_change_done'

url(r'^password-change-done/$', 'password_change_done',
    {'template_name': 'userauth/password_change_done.html'},
    name='password_change_done'),

我查看了 django.contrib.auth.views.password_change(这是造成问题的原因)并意识到 url 'password_change_done' 在 Django 1.8.2 中是硬编码的。

您需要删除视图名称两边的单引号

{% url password_change_done %}

而不是

{% url 'password_change_done' %}

好的,所以为我建议的解决方案在这里不起作用。我在具有特定应用标签的应用程序中使用 Django 1.8.8,因此我需要在这样的模板中指定 url,例如app_label:url_name。这意味着 password_change_done 的反向操作永远不会起作用,因为它是 app_label:password_change_done。

但幸运的是有一个解决方案:'post_change_redirect'。因此我这样指定 password_change:

url(r'^password_change$', 'django.contrib.auth.views.password_change', {'template_name': 'password_change.html', 'post_change_redirect': 'app_label:password_change_done'}, name='password_change'),

我相信其他人可以使用它来克服上述问题并仍然保留他们自己的自定义 url 名称。

我遇到了同样的问题。原因是 "password_change_done" 是 auth.views 中的硬代码,所以我在 auth.views.PasswordChangeView 的基础上扩展了 class。

auth.views.PasswordChangeView:

class PasswordChangeView(PasswordContextMixin, FormView):
......
success_url = reverse_lazy('password_change_done')

MyPasswordChangeView:

class MyPasswordChangeView(PasswordChangeView):
    success_url = reverse_lazy('app_label:password_change_done')

只需覆盖 success_url

并在 urlpattern 中使用 MyPasswordChangeView。现在,一切正常。

如果您使用

app_name

并尝试覆盖 update/change 密码的默认模板,您必须告诉 Django:

from django.urls import path, reverse_lazy
from django.contrib.auth import views as auth_view
from . import views

app_name = 'account'

urlpatterns = [
    path('login/', auth_view.LoginView.as_view(), name='login'),
    path('logout/', auth_view.LogoutView.as_view(), name='logout'),

    path('password_change/',
         auth_view.PasswordChangeView.as_view(
             template_name='registration/password_change_form.html',
             success_url=reverse_lazy('account:password_change_done')), name='password_change'),

    path('password_change/done/',
         auth_view.PasswordChangeDoneView.as_view(
             template_name='registration/password_change_done.html'), name='password_change_done'),
]