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