Django-nonrel + Django-registration problem: unexpected keyword argument 'uidb36' when resetting password
Asked Answered
B

4

21

I'm using Django-nonrel with registration app. Things seem to be working fine, except when I try to reset my password. When clicking on reset-password link sent to me in email, Django produces error message:

password_reset_confirm() got an unexpected keyword argument 'uidb36'

My question: has anybody seen it and knows what's the cure?

EDIT:

The problem is caused by registration\auth_urls.py - they duplicate entries in django\contrib\auth\urls.py, circumwenting patched version of the file in Django-nonrel.

Any ideas why is it there and can I actually remove it or fix it otherwise?

Binaural answered 12/6, 2011 at 18:42 Comment(0)
B
9

My solution was to comment out urlpatterns defined in registration\auth_urls.py, and redefine them as a copy of urlpatterns defined in django.contrib.auth.

Here's my auth_urls.py after the change:

"""
URL patterns for the views included in ``django.contrib.auth``.

Including these URLs (via the ``include()`` directive) will set up the
following patterns based at whatever URL prefix they are included
under:

* User login at ``login/``.

* User logout at ``logout/``.

* The two-step password change at ``password/change/`` and
  ``password/change/done/``.

* The four-step password reset at ``password/reset/``,
  ``password/reset/confirm/``, ``password/reset/complete/`` and
  ``password/reset/done/``.

The default registration backend already has an ``include()`` for
these URLs, so under the default setup it is not necessary to manually
include these views. Other backends may or may not include them;
consult a specific backend's documentation for details.

"""

from django.conf.urls.defaults import *

#from django.contrib.auth import views as auth_views

from django.contrib.auth import urls as auth_urls

urlpatterns = auth_urls.urlpatterns

'''
Commented out, this is what caused my problems:

urlpatterns = patterns('',
                       url(r'^login/$',
                           auth_views.login,
                           {'template_name': 'registration/login.html'},
                           name='auth_login'),
                       url(r'^logout/$',
                           auth_views.logout,
                           {'template_name': 'registration/logout.html'},
                           name='auth_logout'),
                       url(r'^password/change/$',
                           auth_views.password_change,
                           name='auth_password_change'),
                       url(r'^password/change/done/$',
                           auth_views.password_change_done,
                           name='auth_password_change_done'),
                       url(r'^password/reset/$',
                           auth_views.password_reset,
                           name='auth_password_reset'),
                       url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
                           auth_views.password_reset_confirm,
                           name='auth_password_reset_confirm'),
                       url(r'^password/reset/complete/$',
                           auth_views.password_reset_complete,
                           name='auth_password_reset_complete'),
                       url(r'^password/reset/done/$',
                           auth_views.password_reset_done,
                           name='auth_password_reset_done'),
) 
'''
Binaural answered 13/6, 2011 at 0:22 Comment(2)
which Django version are you using? I'm having the same problem, but it seems that the file structure of my auth app is a bit different than yours.Frottage
I've downloaded the latest Django-nonrel. Looking at my django_init_ I see: VERSION = (1, 3, 0, 'final', 0), so that must be Django 1.3.Binaural
C
34

Django 1.6 uses base 64 encoding for the User's ID instead of base 36 encoding.

If you have any custom password reset URLs, you will need to update them by replacing uidb36 with uidb64 and the dash that follows that pattern with a slash. Also add "_", "\" and "-" to the list of characters that may match the uidb64 pattern.

For example this line in urls.py in Django 1.5-:

url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
    'django.contrib.auth.views.password_reset_confirm',
    name='password_reset_confirm'),

Will need to be changed to this in Django 1.6+:

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

Here is the official changelog which details the change: https://docs.djangoproject.com/en/1.6/releases/1.6/#django-contrib-auth-password-reset-uses-base-64-encoding-of-user-pk

Cummings answered 3/12, 2013 at 21:51 Comment(2)
correct me if i'm wrong, but this question was way before django 1.6, correct? Still, a good link with good infoHanley
It's possible that he was using a beta build, or that the registration app updated their URL patterns in anticipation. Either way I think the solution would work for him.Cummings
B
9

My solution was to comment out urlpatterns defined in registration\auth_urls.py, and redefine them as a copy of urlpatterns defined in django.contrib.auth.

Here's my auth_urls.py after the change:

"""
URL patterns for the views included in ``django.contrib.auth``.

Including these URLs (via the ``include()`` directive) will set up the
following patterns based at whatever URL prefix they are included
under:

* User login at ``login/``.

* User logout at ``logout/``.

* The two-step password change at ``password/change/`` and
  ``password/change/done/``.

* The four-step password reset at ``password/reset/``,
  ``password/reset/confirm/``, ``password/reset/complete/`` and
  ``password/reset/done/``.

The default registration backend already has an ``include()`` for
these URLs, so under the default setup it is not necessary to manually
include these views. Other backends may or may not include them;
consult a specific backend's documentation for details.

"""

from django.conf.urls.defaults import *

#from django.contrib.auth import views as auth_views

from django.contrib.auth import urls as auth_urls

urlpatterns = auth_urls.urlpatterns

'''
Commented out, this is what caused my problems:

urlpatterns = patterns('',
                       url(r'^login/$',
                           auth_views.login,
                           {'template_name': 'registration/login.html'},
                           name='auth_login'),
                       url(r'^logout/$',
                           auth_views.logout,
                           {'template_name': 'registration/logout.html'},
                           name='auth_logout'),
                       url(r'^password/change/$',
                           auth_views.password_change,
                           name='auth_password_change'),
                       url(r'^password/change/done/$',
                           auth_views.password_change_done,
                           name='auth_password_change_done'),
                       url(r'^password/reset/$',
                           auth_views.password_reset,
                           name='auth_password_reset'),
                       url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
                           auth_views.password_reset_confirm,
                           name='auth_password_reset_confirm'),
                       url(r'^password/reset/complete/$',
                           auth_views.password_reset_complete,
                           name='auth_password_reset_complete'),
                       url(r'^password/reset/done/$',
                           auth_views.password_reset_done,
                           name='auth_password_reset_done'),
) 
'''
Binaural answered 13/6, 2011 at 0:22 Comment(2)
which Django version are you using? I'm having the same problem, but it seems that the file structure of my auth app is a bit different than yours.Frottage
I've downloaded the latest Django-nonrel. Looking at my django_init_ I see: VERSION = (1, 3, 0, 'final', 0), so that must be Django 1.3.Binaural
H
5

I just had to change the uidb36 argument to uidb64, like so:

FROM:

url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',

TO:

url(r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',

Then password resets began working again.

Headband answered 21/12, 2011 at 20:18 Comment(0)
C
1

I guess your password_reset_confirm url in urls.py looks something similar to

url(r'^accounts/password_reset/(?P[0-9A-Za-z]{1,13})-(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', password_reset_confirm, {'post_reset_redirect' : '/accounts/password_reset/complete/'},name="password_reset_confirm"),

and your link in password_reset_email.html looks like {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb36=uid token=token %}

Just change uib36 to uib64 both the places,it works.

Clinkscales answered 16/2, 2017 at 6:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.