4

I'm working on authentication for a Django project I'm working on. For some reasons, I'm getting the error Reverse for 'password_reset_done' not found. 'password_reset_done' is not a valid view function or pattern name. I put everything authentication in an accounts app.

Here's the content of the base urls.py file:

from django.contrib import admin
from django.urls import path, include
from accounts import urls as accounts_urls
from core import urls as core_urls
from core import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('accounts/', include(accounts_urls, namespace='accounts')),
    path('core/', include(core_urls, namespace='core')),
]

Here's the content of the urls.py file (in the accounts app):

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

app_name = 'accounts'

urlpatterns = [
    path('signup/', accounts_views.signup, name='signup'),
    path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
    path('account_activation_sent/', accounts_views.account_activation_sent, name='account_activation_sent'),
    path('activate/<uidb64>/<token>/', accounts_views.activate, name='activate'),
    path('password_reset/', auth_views.PasswordResetView.as_view(
        template_name='accounts/password_reset.html',
        email_template_name='accounts/password_reset_email.html',
        subject_template_name='accounts/password_reset_subject.txt'
    ), name='password_reset'),
    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(
        template_name='accounts/password_reset_done.html'
    ), name='password_reset_done'),
    path('password_reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(
        template_name='accounts/password_reset_confirm.html'
    ), name='password_reset_confirm'),
    path('password_reset/complete/', auth_views.PasswordResetCompleteView.as_view(
        template_name='accounts/password_reset_complete.html'
    ), name='password_reset_complete'),
]

Here's the accounts/templates directory structure:

  • templates/
    • accounts/
      • password_reset.html
      • password_reset_email.html
      • password_reset_done.html
      • password_reset_confirm.html
      • password_reset_complete.html

I don't see anything wrong with what I have done so far. Any eye opener would be greatly appreciated, thanks!

Caspian
  • 633
  • 1
  • 10
  • 29
  • As an aside, you don't need `namespace='accounts'` when you already have `app_name = 'accounts'` in the `urls.py`. – Alasdair Sep 12 '18 at 11:10

4 Answers4

5

I figured it out! Since I wanted to have more control over URLs, I changed the default Password Reset patterns. I was also bent on using namespaces so I changed the default success_url attribute in PasswordResetView and PasswordResetConfirmView to use the namespace. Here's what I mean:

from django.urls import path, reverse_lazy, include
from django.contrib.auth import views as auth_views
# Add other necessary imports

app_name = 'accounts'

urlpatterns = [    
    path('password_reset/', auth_views.PasswordResetView.as_view(
        template_name='accounts/password_reset.html',
        email_template_name='accounts/password_reset_email.html',
        subject_template_name='accounts/password_reset_subject.txt',
        success_url=reverse_lazy('accounts:password_reset_done')
    ), name='password_reset'),
    path('password_reset_done/', auth_views.PasswordResetDoneView.as_view(
        template_name='accounts/password_reset_done.html'
    ), name='password_reset_done'),
    path('password_reset_<uidb64>_<token>/', auth_views.PasswordResetConfirmView.as_view(
        template_name='accounts/password_reset_confirm.html',
        success_url=reverse_lazy('accounts:password_reset_complete')
    ), name='password_reset_confirm'),
    path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(
        template_name='accounts/password_reset_complete.html'
    ), name='password_reset_complete'),
]
Caspian
  • 633
  • 1
  • 10
  • 29
3

Caspian I believe, you found the solution to my problem,

Moving from Django 2.0 to 2.1, I was going nuts trying to correct my password app to the new required configuration... I could not understand the problem... I did not improve on your solution, but here are my URL codes and it does confirm introducing "success_url=reverse_lazy" your solution works great.

path('password_reset/', 
    PasswordResetView.as_view(
    template_name='app98/password_reset.html',
    email_template_name='app98/password_reset_email.html',
    subject_template_name='app98/password_reset_subject.txt',
    success_url=reverse_lazy('ns_app98:password_reset_done')), 
    name='password_reset'),

path('password_reset_done/', 
    PasswordResetDoneView.as_view(
    template_name='app98/password_reset_done.html'), 
    name='password_reset_done'),

path('password_reset_<uidb64>_<token>/', 
    PasswordResetConfirmView.as_view(
    template_name='app98/password_reset_confirm.html',
    success_url=reverse_lazy('app98:password_reset_complete')), 
    name='password_reset_confirm'),

path('password_reset_complete/', 
    PasswordResetCompleteView.as_view(
    template_name='app98/password_reset_complete.html'), 
    name='password_reset_complete'),

]

1

Because your password_reset_done is namespaced under accounts, you need to be reversing accounts:password_reset_done.

Hope this helps.

danwilson
  • 186
  • 1
  • 8
1

The Django auth views do not use a namespace when reversing urls. This means that it doesn't work with your current urls, since you have app_name = 'account' and namespace='accounts'.

The simplest solution is to remove the accounts app name and namespace (or move the password URL patterns into a different urls.py that doesn't have a namespace.

It is possible to subclass the password views and reverse using a namespace, but there's quite a lot of changes required.

Alasdair
  • 298,606
  • 55
  • 578
  • 516