web-dev-qa-db-ja.com

Django 2、python 3.4はurlsafe_base64_decode(uidb64)をデコードできません)

私は電子メール、電子メールの作品、エンコーディングの作品でユーザーをアクティブ化しようとしています、私はDjango1.11からのアプローチを使用しました。

Django 1.11では、以下は正常に28にデコードされます。ここで、uidb64 = b'Mjg '

force_text(urlsafe_base64_decode(uidb64))

Django 2(2、0、0、 'final'、0)では、上記のコードデコードは機能せず、エラーが発生します

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

念のため自分の意見も投稿しています

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を使用する前の試用版です。

編集:トレースバックを含む

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) 
15
Vipin Mohan

OK。 1時間の長い検索(まだ初心者python Django))の後、関連する変更がリリースノートで指摘されましたが、その定義は初心者にとっては少し難しいものでした。 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()は、force_text()ではなくstr()を使用して、URLに配置する前に、受け取った引数とkwargsを強制します。バイト文字列の場合、これにより、不要なb接頭辞と追加の引用符を含む文字列が作成されます(str(b'foo ')は "b'foo'")。適応するには、バイト文字列に対してdecode()を呼び出してから、それをreverse()に渡します。

その影響を完全に処理することはできません。実際のDjangoコアコードを深く掘り下げる必要がありました。

Django 1.11 to 2.0から、エンコードの変更は次のようになります。

_'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()
_

それでおしまい。これが誰かを助けることを願っています。

*************編集******************

Django 2.2現在

Django.utils.http.urlsafe_base64_encode()は、バイト文字列ではなく文字列を返すようになりました。

また、Django.utils.http.urlsafe_base64_decode()にバイト文字列を渡すことはできなくなりました。

指摘してくれたHillmarkに感謝

42
Vipin Mohan