Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NoReverseMatch at /rest-auth/password/reset/

I have a django application with an angular front-end. When from the front-end I try to send a request for passwordReset, I get the following error:

Reverse for 'password_reset_confirm' with arguments '()' and keyword arguments '{u'uidb64': 'MTE', u'token': u'3z4-eadc7ab3866d7d9436cb'}' not found. 0 pattern(s) tried: []

Its a POST request going to http://127.0.0.1:8080/rest-auth/password/reset/

Following is what my urls.py looks like:

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'))
)
like image 617
birdy Avatar asked Feb 09 '15 19:02

birdy


5 Answers

I also was having this problem, and found this github issue it said we need to add

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

on the urlpatterns.

As stated there it says that The PasswordReset view depends on django.contrib.auth.views.password_reset_confirm view.

like image 155
Abimael Carrasquillo Avatar answered Nov 20 '22 09:11

Abimael Carrasquillo


As Roar Skullestad pointed out, the problem is with the default email template, which tries to resolve URL by reversing viewname "password_reset_confirm", which is undefined.

It is enough to register a viewname "password_reset_confirm" with a custom route and then default email template rendering will work fine.

You can register viewname with custom route by adding a path to urls.py:

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

password-reset - custom route that password reset confirmation view. If you have SPA (Angular) - it will be the URL of your SPA view (such as the route to Angular component) that will handle the password reset.

This is the URL that will be resolved and embedded in the email. For this example it will be something like:

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

empty_view - in case of SPA (Angular), you don't really need server-side implementation, because the front end will actually handle this route. I used this implementation of a view, but it can be anything else:

from django.http import HttpResponse

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

And since I'm using Angular, this is the route for my Angular component:

{
    path: 'password-reset/:uid/:token',
    component: PasswordRecoveryComponent
}
like image 20
Vitali Kaspler Avatar answered Nov 20 '22 09:11

Vitali Kaspler


For me the problem was this line in site-packages/django/contrib/admin/templates/registration/password_reset_email.html:

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

From what I understand the problem is caused by reverse lookup not working for this line in 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'),

My (at least temporarily) solution was to override the template and hardcode the reverse lookup part of the url for the link in the email.

The path to the new template is specified in settings.py:

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

Since I am using angular front end, I also changed the link so that it triggers password reset confirmation via the angular client:

{{ protocol }}://{{ domain }}/#/passwordResetConfirm/{{ uid }}/{{ token }}
like image 6
Roar Skullestad Avatar answered Nov 20 '22 10:11

Roar Skullestad


@AbimaelCarrasquillo's solutions works but you probably do not want to expose those endpoints as @dpstart mentioned in the comments.

I solved this by overriding the PasswordResetSerializer of rest-auth and simply replacing the reset form:

password_reset_form_class = PasswordResetForm

from the internal django.contrib.auth.forms.PasswordResetForm to allauth.account.forms.ResetPasswordForm

Make sure to add the following to your settings:

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER':'path.to.PasswordResetSerializer'
}
like image 3
bahmsto Avatar answered Nov 20 '22 11:11

bahmsto


For those who are still struggling with this issue, I found that the reverse look up internal view looks for reverse lookup within the core project urls and not within any application. It could work within application with some tweak, but I am not sure. But it works creating the reset urls directly on core project urls.py

{
    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'),
}
like image 1
Sureshbabu E Avatar answered Nov 20 '22 09:11

Sureshbabu E