I have these views for registering and activating new user accounts:
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.sites.shortcuts import get_current_site
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes, force_str
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
#from orders.views import user_orders
from .forms import RegistrationForm
from .models import UserBase
from .tokens import account_activation_token
def account_register(request):
if request.method == 'POST':
registerForm = RegistrationForm(request.POST)
if registerForm.is_valid():
user = registerForm.save(commit=False)
user.email = registerForm.cleaned_data['email']
user.set_password(registerForm.cleaned_data['password'])
user.is_active=False
user.save()
#E-mail setup
current_site = get_current_site(request)
subject = 'Activate your Account'
message = render_to_string('users/registration/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
user.email_user(subject=subject, message=message)
return HttpResponse('registered succesfully and activation sent')
else:
registerForm = RegistrationForm()
return render(request, 'users/registration/register.html', {'form': registerForm})
def account_activate(request, token, uidb64):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
print('uid:', uid)
user = UserBase.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, UserBase.DoesNotExist):
user = None
print(user)
print(token)
print(account_activation_token.check_token(user, token))
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
return redirect('users:dashboard')
else:
return render(request, 'users/registration/activation_invalid.html')
@login_required
def dashboard(request):
orders = user_orders(request)
return render(
request,
'users/user/dashboard.html',
{'section': 'profile', 'orders': orders}
)
Since this is my first project, I’m using a tutorial to teach me the ropes. It uses a base64-encoded ID as well as a custom token to generate an activation link. The method used to decode the user ID to a URL friendly format works fine, however to convert it to a format that can be used by python to fetch the user object they used force_text
on the decoding function, which was removed from Django some time ago.
In my current account_activate()
view, Django is able to decode uid
(the user ID originally encoded in base64), but it’s not in a format that UserBase.objects.get(pk=uid)
can’t recognize, and therefore the exception is executed and user
becomes None. I found on the internet that, since force_text()
has been removed I should use force_str()
, but in my code it can’t process the decoded uid. Is there something else I can use to get the user object from the decoded ID?