NoReverseMatch at / rest-auth / password / reset /

时间:2015-02-09 19:59:30

标签: python django authentication

我有一个带角度前端的django应用程序。当我从前端尝试发送passwordReset请求时,我收到以下错误:

  

使用参数'()'和关键字反转'password_reset_confirm'   参数'{​​u'uidb64':'MTE',u'token':u'3z4-eadc7ab3866d7d9436cb'}'   未找到。尝试了0种模式:[]

它的POST请求转到http://127.0.0.1:8080/rest-auth/password/reset/

以下是我的urls.py的样子:

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

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^rest-auth/', include('rest_auth.urls')),
    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
    url(r'^account/', include('allauth.urls'))
)

12 个答案:

答案 0 :(得分:24)

我也遇到了这个问题,发现这个github issue它说我们需要添加

url(r'^', include('django.contrib.auth.urls')),

在urlpatterns上。

如上所述,它说PasswordReset视图取决于django.contrib.auth.views.password_reset_confirm视图。

答案 1 :(得分:5)

正如Roar Skullestad指出的那样,问题出在默认的电子邮件模板上,该模板试图通过reversing视图名“ password_reset_confirm”来解析URL,该URL未定义。

使用自定义路由注册视图名称“ password_reset_confirm”就足够了,然后默认的电子邮件模板呈现将正常工作。

您可以通过向urls.py添加路径来使用自定义路由注册视图名称:

urlpatterns = [
    ...,
    path('password-reset/<uidb64>/<token>/', empty_view, name='password_reset_confirm'),
]

密码重置-自定义路由,该密码重置确认视图。如果您有SPA(Angular),它将是您的SPA视图的URL(例如到Angular组件的路由),将处理密码重置。

这是将解析并嵌入到电子邮件中的URL。对于此示例,它将类似于:

  

http://my-spa.com/app-name/password-reset/Nw/51v-490d4b372ec930e49049/

empty_view -对于SPA(Angular),您实际上不需要服务器端实现,因为前端实际上会处理此路由。我使用了视图的这种实现,但是可以是其他任何形式:

from django.http import HttpResponse

def empty_view(request):
    return HttpResponse('')

由于我使用的是Angular,这是我的Angular组件的路由:

{
    path: 'password-reset/:uid/:token',
    component: PasswordRecoveryComponent
}

答案 2 :(得分:4)

对我来说,问题是site-packages / django / contrib / admin / templates / registration / password_reset_email.html中的这一行:

{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

根据我的理解,问题是由在contrib / auth / urls.py中反向查找不适用于此行引起的:

    url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
    'django.contrib.auth.views.password_reset_confirm',
    name='password_reset_confirm'),

我的(至少是暂时的)解决方案是覆盖模板并硬编码电子邮件中链接的URL的反向查找部分。

新模板的路径在settings.py中指定:

TEMPLATE_DIRS =(
    "/absolute/path/to/my/templates/directory",
)

由于我使用的是角度前端,我还更改了链接,以便通过角度客户端触发密码重置确认:

{{ protocol }}://{{ domain }}/#/passwordResetConfirm/{{ uid }}/{{ token }}

答案 3 :(得分:3)

@ AbimaelCarrasquillo的解决方案有效,但您可能不希望将这些端点公开为评论中提到的@dpstart。

我通过覆盖rest-auth的PasswordResetSerializer并简单地替换重置形式来解决这个问题:

password_reset_form_class = PasswordResetForm

从内部django.contrib.auth.forms.PasswordResetFormallauth.account.forms.ResetPasswordForm

确保将以下内容添加到您的设置中:

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER':'path.to.PasswordResetSerializer'
}

答案 4 :(得分:1)

嗯,我也遇到了这个问题。每次我输入电子邮件并按下按钮时,它都会将我带到 NoReverseMatch 网址,我正在使用:

re_path(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
TemplateView.as_view(template_name="password_reset_confirm.html"),name='password_reset_confirm')

(不再使用 django 中的 url 匹配正则表达式,而是使用 re_path)

我的解决方案是稍微更改正则表达式,因为 “csrf 令牌” 的长度超过 20 个字 - 这就是我收到错误的原因,您应该尝试相同的方法。

re_path(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,40})/$',
TemplateView.as_view(template_name="password_reset_confirm.html"),
name='password_reset_confirm')

您可以使用 +(在正则表达式中表示一个或多个)或 {1,40} (在正则表达式中表示匹配从 1 到 40)

答案 5 :(得分:0)

将此项添加到项目url.py文件

url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url('', include('social.apps.django_app.urls', namespace='social')),

答案 6 :(得分:0)

查看FAQ:它说明了此错误以及如何解决。它会将您引向演示程序,其中包含:

# this url is used to generate email content
url(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
    TemplateView.as_view(template_name="password_reset_confirm.html"),
    name='password_reset_confirm'),

答案 7 :(得分:0)

对于那些仍在为这个问题苦苦挣扎的人,我发现反向查找内部视图在核心项目url中而不是在任何应用程序中查找反向查找。它可以在应用程序中进行一些调整,但我不确定。但是它可以直接在核心项目urls.py

上创建重置URL。

{     路径(r'password_reset /',PasswordResetView.as_view(template_name ='password_reset_form.html'),name ='password_reset'),     路径(r'password_reset_done /',PasswordResetDoneView.as_view(template_name ='password_reset_done.html'),name ='password_reset_done'),     路径(r'password_reset_confirm ///',PasswordResetConfirmView.as_view(template_name ='password_reset_confirm.html'),name ='password_reset_confirm'),     路径(r'password_reset_complete /',PasswordResetCompleteView.as_view(template_name ='password_reset_complete.html'),name ='password_reset_complete'), }

答案 8 :(得分:0)

我的解决方案是覆盖调用“ password_reset_confirm”相反的电子邮件模板。确保电子邮件模板使用URL中的UID和令牌将URL发送到您的前端应用程序(而不是尝试撤消“ password_reset_confirm”)。

您的前端路由应采用URL,先进行解析,然后使用更新的用户密码,然后将其作为API调用发送回后端以进行确认。

答案 9 :(得分:0)

我通过移动这些按钮解决了这个问题:

path('reset_password/', auth_views.PasswordResetView.as_view(), name='password_reset'),
path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset_password_sent/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset_password_complete/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),

accounts / urls.py yourProjectName / urls.py

我猜是path('', include("accounts.urls")),引起了问题。

答案 10 :(得分:0)

我有一个无头后端,因此仅添加或重命名URL并不是一个好的选择。 问题出在电子邮件模板上,您可以覆盖它。只要注意您在设置上的正确路径即可。 就我而言,我在用户应用程序中拥有所有这些逻辑。所以我有这样的东西。

users/templates/registration/password_reset_email.html

在此模板中,我有一条新的自定义消息,没有反向URL调用。 如果您不仅需要覆盖模板,还需要向模板发送其他数据。您还必须覆盖串行器。为此,您必须创建新的序列化器

from dj_rest_auth.serializers import PasswordResetSerializer as RestPasswordResetSerializer


class PasswordResetSerializer(RestPasswordResetSerializer):

    def get_email_options(self):
        return {
            'html_email_template_name': 'registration/password_reset_email_html.html',  # if you want to use an HTML template you can declare here
            'extra_email_context': {'custom_key': 'custom value for my template',}
        }

并添加到设置。

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER':'path.to.PasswordResetSerializer'
}

在序列化程序上,您还可以根据需要添加自定义验证。

答案 11 :(得分:0)

在你的views.py中,如果你设置了一个token,把它和类似的路径一起传递:

path('resetpassword_validate/<uidb64>/<token>/', views.resetpassword_validate, name='resetpassword_validate'),