[Django]-Django 2, python 3.4 cannot decode urlsafe_base64_decode(uidb64)

60👍

Ok. after hour long search (still beginner at python django), a relevant change was pointed in release notes whose definitions were little difficult for a newcomer.
https://docs.djangoproject.com/en/2.0/releases/2.0/#removed-support-for-bytestrings-in-some-places

To support native Python 2 strings, older Django versions had to accept both bytestrings and unicode strings. Now that Python 2 support is dropped, bytestrings should only be encountered around input/output boundaries (handling of binary fields or HTTP streams, for example). You might have to update your code to limit bytestring usage to a minimum, as Django no longer accepts bytestrings in certain code paths.

For example, reverse() now uses str() instead of force_text() to
coerce the args and kwargs it receives, prior to their placement in
the URL. For bytestrings, this creates a string with an undesired b
prefix as well as additional quotes (str(b’foo’) is “b’foo'”). To
adapt, call decode() on the bytestring before passing it to reverse().

Totally unable to work on its implications, i had to go deeper into the actual django core code.

So from django 1.11 to 2.0 the encode change is as follows

'uid': urlsafe_base64_encode(force_bytes(user.pk)),

to

'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),

and decode from

uid = force_text(urlsafe_base64_decode(uidb64))

to

 uid = urlsafe_base64_decode(uidb64).decode()

Thats it. Hope this helps someone.

*************EDIT******************

As of Django 2.2

django.utils.http.urlsafe_base64_encode() now returns a string instead of a bytestring.

And django.utils.http.urlsafe_base64_decode() may no longer be passed a bytestring.

Thanks to Hillmark for pointing it out

Leave a comment