本文介绍了Django 2、python 3.4 无法解码 urlsafe_base64_decode(uidb64)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过电子邮件激活用户,电子邮件有效,编码有效,我使用了 django1.11 中的方法,该方法运行成功.

i am trying to activate a user by email,email works, encoding works, i used an approach from django1.11 which was working successfully.

在 Django 1.11 中,以下成功解码为 28,其中 uidb64 = b'Mjg'

In Django 1.11 the following decodes successfully to 28, where uidb64 = b'Mjg'

force_text(urlsafe_base64_decode(uidb64))

在 django 2 (2, 0, 0, 'final', 0) 上面的代码解码不起作用并导致错误

In django 2 (2, 0, 0, 'final', 0) the above code decode does not work and results in an error

django.utils.encoding.DjangoUnicodeDecodeError: 'utf-8' codec can't decode byte 0xc8 in position 1: invalid continuation byte. You passed in b'lxc8xe0' (<class 'bytes'>)

为了以防万一,我也发表一下我的看法

I am also posting my views just in case

from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            # auth_login(request, user)
            message = render_to_string('user_activate_email.html', {
                'user': user,
                'domain': Site.objects.get_current().domain,
                'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),
                'token': account_activation_token.make_token(user),
            })
            mail_subject = 'Activate your blog account.'
            to_email = form.cleaned_data.get('email')
            email = EmailMessage(mail_subject, message, to=[to_email])
            email.send()
            messages.info(
                request, 'Activation link has been sent to your email!')
            # return redirect('home')
            return render(request, 'index.html')
    else:
        form = SignUpForm()
        return render(request, 'user_action.html', {'form': form})


def activate(request, uidb64, token):
    try:
        import pdb;
        pdb.set_trace()
        uid = urlsafe_base64_decode(uidb64).decode()
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError):
        user = None
    if user is not None and account_activation_token.check_token(user, token):

        user.refresh_from_db()
        user.is_active = True

        user.save()
        auth_login(request, user)
        messages.info(request, 'Your account has been activated successfully!')
        return redirect('events:home')
    else:
        messages.info(
            request, 'Activation link is invalid or has been activated')
        return redirect('events:home')

PS:这只是我在与 CBV 合作之前的一次尝试.

PS: This is just a trial before i work with CBV.

包括回溯

System check identified no issues (0 silenced).
December 15, 2017 - 05:51:01
Django version 2.0, using settings 'event_management.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
> /home/vipinmohan/django2-0/event/event_management/users/views.py(88)activate()
-> uid = urlsafe_base64_decode(uidb64).decode()
(Pdb) n
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcc in position 1: invalid continuation byte
> /home/vipinmohan/django2-0/event/event_management/users/views.py(88)activate()
-> uid = urlsafe_base64_decode(uidb64).decode()
(Pdb) n
> /home/vipinmohan/django2-0/event/event_management/users/views.py(90)activate()
-> except(TypeError, ValueError, OverflowError):
(Pdb) n
> /home/vipinmohan/django2-0/event/event_management/users/views.py(91)activate()
-> user = None
(Pdb)

推荐答案

好的.经过一个小时的搜索(仍然是python django的初学者),发布说明中指出了一个相关的变化,其定义对新手来说并不困难.https://docs.djangoproject.com/en/2.0/releases/2.0/#re​​moved-support-for-bytestrings-in-some-places

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

为了支持原生 Python 2 字符串,较旧的 Django 版本必须同时接受字节字符串和 unicode 字符串.既然 Python 2 支持已被删除,字节串只能在输入/输出边界附近遇到(例如,处理二进制字段或 HTTP 流).您可能需要更新代码以将字节串的使用限制在最低限度,因为 Django 不再接受某些代码路径中的字节串.

例如,reverse() 现在使用 str() 而不是 force_text() 来强制它收到的 args 和 kwargs,在它们放入之前网址.对于字节串,这会创建一个带有不想要的 b 的字符串前缀以及附加引号(str(b'foo') 是 "b'foo'").到适应,在将字节串传递给 reverse() 之前调用 decode().

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().

完全无法解决它的影响,我不得不更深入地研究实际的 django 核心代码.

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

所以从 django 1.11 到 2.0 编码变化如下

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

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

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

并从

uid = force_text(urlsafe_base64_decode(uidb64))

 uid = urlsafe_base64_decode(uidb64).decode()

就是这样.希望这对某人有所帮助.

Thats it. Hope this helps someone.

****************编辑********************

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

从 Django 2.2 开始

django.utils.http.urlsafe_base64_encode() 现在返回字符串而不是字节字符串.

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

并且 django.utils.http.urlsafe_base64_decode() 可能不再传递字节串.

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

感谢 Hillmark 指出

Thanks to Hillmark for pointing it out

这篇关于Django 2、python 3.4 无法解码 urlsafe_base64_decode(uidb64)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 15:27