【问题标题】:NoReverseMatch at /rest-auth/password/reset/NoReverseMatch 在 /rest-auth/password/reset/
【发布时间】:2015-04-09 16:36:36
【问题描述】:

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

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

这是一个发往http://127.0.0.1:8080/rest-auth/password/reset/的POST请求

以下是我的 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'))
)

【问题讨论】:

  • 您可能需要向我们展示rest_auth.urls 的网址。
  • 您找到解决方案了吗?

标签: python django authentication


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    嗯,我也遇到了这个问题。每次我输入我的电子邮件并按下按钮时,我都会转到 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 token" 超过 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的匹配)

    【讨论】:

      【解决方案3】:

      我有一个无头后端,因此仅为此添加或重命名 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'
      }
      

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

      【讨论】:

        【解决方案4】:

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

        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.pyyourProjectName/urls.py

        我猜是path('', include("accounts.urls")), 导致了这个问题。

        【讨论】:

          【解决方案5】:

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

          {
              path(r'password_reset/', PasswordResetView.as_view(template_name='password_reset_form.html'), name='password_reset'),
              path(r'password_reset_done/', PasswordResetDoneView.as_view(template_name='password_reset_done.html'), name='password_reset_done'),
              path(r'password_reset_confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'), name='password_reset_confirm'),
              path(r'password_reset_complete/', PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'), name='password_reset_complete'),
          }
          

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

              【解决方案7】:

              查看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'),
              

              【讨论】:

                【解决方案8】:

                正如 Roar Skullestad 指出的那样,问题出在默认电子邮件模板上,它试图通过未定义的 reversing viewname "password_reset_confirm" 解析 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
                }
                

                【讨论】:

                  【解决方案9】:

                  @AbimaelCarrasquillo 的解决方案有效,但您可能不想像 cmets 中提到的 @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'
                  }
                  

                  【讨论】:

                  • 我尝试创建一个新文件 passwordserializer.py 并将定义 PasswordResetSerializer 的代码粘贴到其中,顶部带有“from allauth.account.forms import ResetPasswordForm”。我收到此错误:ValueError: no enough values to unpack (expected 2, got 1)。知道可能是什么问题吗?在 settings.py 中: REST_AUTH_SERIALIZERS = { 'PASSWORD_RESET_SERIALIZER':os.path.join(BASE_DIR, 'PasswordResetSerializer') }
                  【解决方案10】:

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

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

                  【讨论】:

                    【解决方案11】:

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

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

                    在 urlpatterns 上。

                    正如那里所说,PasswordReset 视图取决于django.contrib.auth.views.password_reset_confirm 视图。

                    【讨论】:

                    • 这将解决reverse URL 查找失败时引发的异常,但只会转移问题。查看 Roar 和 Vitali 的答案。
                    • path('', include('django.contrib.auth.urls')), 为我工作
                    • 这种方法的问题是在电子邮件模板上发送的 url 将来自 API,而不是前端需要的。覆盖电子邮件模板更干净(我认为)。
                    【解决方案12】:

                    对我来说,问题是 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",
                    )
                    

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

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2018-07-18
                      • 2014-11-20
                      • 2019-05-28
                      • 1970-01-01
                      • 2019-08-26
                      • 2014-11-29
                      • 2021-03-13
                      • 1970-01-01
                      相关资源
                      最近更新 更多