Reverse Lookup Failure on password change/reset views

3,057 views
Skip to first unread message

Peter

unread,
Jul 24, 2013, 2:11:01 AM7/24/13
to django...@googlegroups.com
I'm probably doing something stupid here but I can't see it.  I'm trying to implement password change and reset using auth, and I'm getting a "No Reverse Match" error for the password_reset_done view.  Normally that would mean that I forgot to creaste a url that calls this view, but I have, and other views in that block (like login) work fine.

So, in my main urls.py I have:


# Registration URLs
urlpatterns += patterns('',
    url(r'^registration/', include('registration.urls', namespace='registration')),
)

and there is no occurrence of 'registration' above this code in the urls.py.

Then, in the registration.urls.py:

from django.conf.urls import patterns, include, url
import django.contrib.auth.views
import registration.views

urlpatterns = patterns('',
    url(r'^login/$', 'django.contrib.auth.views.login', {}, 'login'),
    url(r'^logout/$', 'django.contrib.auth.views.logout', {}, 'logout'),
    url(r'^password_change/$', 'django.contrib.auth.views.password_change',
        {}, name='password_change'),
    url(r'^password_change_done/$', 'django.contrib.auth.views.password_change_done',
        {}, name='password_change_done'),

    url(r'^password_reset/$', 'django.contrib.auth.views.password_reset',
        {}, 'password_reset'),
    url(r'^password_reset_done/$', 'django.contrib.auth.views.password_reset_done',
        {}, 'password_reset_done'),
    url(r'^password_reset_confirm/(?P<uidb36>.+)/(?P<token>.+)/$', 'django.contrib.auth.views.password_reset_confirm',
        {}, 'password_reset_confirm'),
    url(r'^password_reset_complete/$', 'django.contrib.auth.views.password_reset_complete',
        {}, 'password_reset_complete'),

    url(r'^profile/$', registration.views.profile, {}, 'profile'),
    url(r'^profile/edit/$', registration.views.profile_edit, {}, 'profile_edit'),
...

and you can see that a url that invoked password_reset_done actually exists.

But on going to the password reset page: http://127.0.0.1:8000/registration/password_reset/  I get:

NoReverseMatch at /registration/password_reset/

Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found.
Request Method: GET
Request URL: http://127.0.0.1:8000/registration/password_reset/
Django Version: 1.5.1
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found.
Exception Location: /usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 416
Python Executable: /usr/bin/python
Python Version: 2.7.3
Python Path:
['/home/peter/django-sites/simbiant/sched/django-src',
 '/usr/local/lib/python2.7/dist-packages/pytz-2013b-py2.7.egg',
 '/home/peter/django-sites',
 '/home/peter/django-sites/simbiant/sched/django-src',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-linux2',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages/PIL',
 '/usr/lib/python2.7/dist-packages/gst-0.10',
 '/usr/lib/python2.7/dist-packages/gtk-2.0',
 '/usr/lib/pymodules/python2.7',
 '/usr/lib/python2.7/dist-packages/ubuntu-sso-client',
 '/usr/lib/python2.7/dist-packages/ubuntuone-client',
 '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel',
 '/usr/lib/python2.7/dist-packages/ubuntuone-couch',
 '/usr/lib/python2.7/dist-packages/ubuntuone-installer',
 '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
Server time: Wed, 24 Jul 2013 15:21:45 +0930

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/registration/password_reset/

Django Version: 1.5.1
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'django.contrib.flatpages',
 'debug_toolbar',
 'scheduler',
 'registration')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware')


Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/views.py" in password_reset
  147.         post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done')
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse
  496.     return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _reverse_with_prefix
  416.                 "arguments '%s' not found." % (lookup_view_s, args, kwargs))

Exception Type: NoReverseMatch at /registration/password_reset/
Exception Value: Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found.

Any ideas?  Let me know if you think posting Settings or Meta would help.

Pretty sure this is going to be a facepalm...

Cheers,

Peter

Christian Erhardt

unread,
Jul 24, 2013, 2:58:11 AM7/24/13
to django...@googlegroups.com
The problem is, as you already stated the argument for the ReverseMatch. I had this problem once, and the error was that i used the url tag in the template wrong - it changed between two django versions. My urls are defined as yours, in the templates i use: {% url "password_reset_done" parameter %} or {% url "password_reset_xy" %} - the quotation mark made the difference. Just a wild guess, but maybe it helps

Peter

unread,
Jul 24, 2013, 3:16:07 AM7/24/13
to django...@googlegroups.com
> used the url tag in the template wrong - it changed between two django versions

Thanks Christian, but I'm pretty sure the reverse is being invoked from the Django auth code (django.contrib.auth.password_reset) , not my template; nevertheless the template I'm using (registration/password_reset_form.html) is:

{% extends "registration/base_registration.html" %}
{% load i18n %}

{% block title %}{{ block.super }} - {% trans 'Password reset' %}{% endblock %}

{% block pageheading %}{{ block.super }}Password reset{% endblock %}

{% block content %}
<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>

<form action="" method="post">
{{ form.email.errors }}
<p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <input type="submit" value="{% trans 'Reset my password' %}" /></p>
</form>

{% endblock %}

Peter

unread,
Jul 24, 2013, 3:19:41 AM7/24/13
to django...@googlegroups.com
On Wednesday, July 24, 2013 4:46:07 PM UTC+9:30, Peter wrote:
> django.contrib.auth.password_reset

Sorry, that should be: django.contrib.auth.views.password_reset

Peter

unread,
Jul 24, 2013, 3:26:44 AM7/24/13
to django...@googlegroups.com
> Sorry, that should be: django.contrib.auth.views.password_reset

In fact, I'm pretty sure it's this line of code in auth::

File "/usr/local/lib/python2.7/
dist-packages/django/contrib/auth/views.py" in password_reset
  147.         post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done')

The question is: if I actually have a url dispatcher entry that references this view function, then why can't 'reverse' find it?


Daniel Roseman

unread,
Jul 24, 2013, 2:01:03 PM7/24/13
to django...@googlegroups.com
Probably because you've included it under a namespace, so Django would need to look for it as "registration:whatever". There's no need to use the namespace in the include call.
--
DR. 

Peter

unread,
Jul 27, 2013, 3:20:18 AM7/27/13
to django...@googlegroups.com
Yep, that fixed it.  Thanks.

I still think it's wrong of django not to find it by view name though...

anentropic

unread,
Aug 19, 2013, 7:27:57 AM8/19/13
to django...@googlegroups.com
This seems a bug in Django... the `reverse` function is passed the name of a view function, not a named url, so the fact that the url it's being asked to match is included under a namespace shouldn't matter?

(here because I just hit the same problem myself)

anentropic

unread,
Aug 19, 2013, 7:48:24 AM8/19/13
to django...@googlegroups.com
Hmm, well after looking at the source of the `reverse` method I can see that it's not doing what I imagined it was...

I am so used to always naming my urls in urlconfs, when I saw a full import path to a view function like:
reverse('django.contrib.auth.views.password_reset_done')
in the auth/views.py I assumed it ought to find that vew function in whichever urlconf it was defined

Thinking about it, it can't do that because you could easily have more than one url pointing to that function

It means if you have something like this in your root urlconf:
(r'^accounts/', include('django.contrib.auth.urls', namespace="auth")),

then the reverse isn't going to work because it would have to be:
reverse('auth:django.contrib.auth.views.password_reset_done')

in short, don't use a namespace on the built-in auth urls

Arguably, the auth views could work out what namespace they're under and handle it though, eg:
(django/contrib/auth/views.py #147)
resolver = resolve(request.path)
ns = ''
if resolver.namespace:
    ns = resolver.namespace + ':'
post_reset_redirect = reverse('{0}django.contrib.auth.views.password_reset_done'.format(ns))

(admittedly this assumes you have imported all of the auth urls into the same namespace)

William Opondo

unread,
Jan 16, 2014, 4:26:26 AM1/16/14
to django...@googlegroups.com
Hi all, I'm new to django and I am using django 1.6 on my local machine yet the version of django on the company server is 1.5.4 thus I get the following error:
Reverse for 'django.contrib.auth.views.password_reset_confirm' with arguments '()' and keyword arguments '{u'uidb64': u'4', u'token': u'3ob-9370053c94189ea07a08'}' not found.
The error occurs when it tries to perform the following line:
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb64=uid token=token %}

my guess is that there is a change from django 1.5 to 1.6 in how the reverse url is matched. How would I then change the code so that it works with the older version(1.5), could it be the fact the uidb64 was introduced in 1.6 while 1.5 uses uidb36. Would that be the only change needed?
Reply all
Reply to author
Forward
0 new messages