So I have the following token activation setup for users to activate their accounts
JavaScript
x
6
1
# urls.py
2
3
# Activation
4
path('activate/<uidb64>/<token>/',
5
user_views.activate, name='activate'),
6
JavaScript
1
23
23
1
# views.py
2
3
User = get_user_model() # Get custom user model
4
5
def activate(request, uidb64, token):
6
# Debugging
7
uid = force_bytes(urlsafe_base64_decode(uidb64))
8
print(User.objects.get(pk=uid))
9
try:
10
uid = force_bytes(urlsafe_base64_decode(uidb64))
11
user = User.objects.get(pk=uid)
12
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
13
user = None
14
15
if user is not None and account_activation_token.check_token(user, token):
16
user.is_active = True
17
user.email_confirmed = True
18
user.save()
19
login(request, user)
20
return redirect('/dashboard/overview/')
21
else:
22
return render(request, 'user/authentication/account_activation_invalid.html')
23
JavaScript
1
16
16
1
# tokens.py
2
3
from django.contrib.auth.tokens import PasswordResetTokenGenerator
4
import six
5
6
7
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
8
def _make_hash_value(self, user, timestamp):
9
return (
10
six.text_type(user.pk) + six.text_type(timestamp) +
11
six.text_type(user.email_confirmed)
12
)
13
14
15
account_activation_token = AccountActivationTokenGenerator()
16
JavaScript
1
30
30
1
# models.py
2
# Custom usermodel
3
4
class UserProfile(AbstractBaseUser, PermissionsMixin):
5
6
# Unique identifier
7
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
8
9
# Email and name of the user
10
email = models.EmailField(max_length=255, unique=True)
11
name = models.CharField(max_length=255)
12
13
# Privilege and security booleans
14
is_staff = models.BooleanField(default=False)
15
is_superuser = models.BooleanField(default=False)
16
is_active = models.BooleanField(default=False)
17
email_confirmed = models.BooleanField(default=False)
18
19
objects = UserProfileManager()
20
21
USERNAME_FIELD = 'email'
22
REQUIRED_FIELDS = []
23
24
def email_user(self, subject, message, from_email=None, **kwargs):
25
"""Send mail to user - Copied from original class"""
26
send_mail(subject, message, from_email, [self.email], **kwargs)
27
28
def __str__(self):
29
return self.email
30
However, when I click the emailed link, the view always returns the isn't valid
path.
Some debugging pointed me to print(User.objects.get(pk=uid))
which returns
TypeError: a bytes-like object is required, not ‘str’ [01/Sep/2022 04:18:57] “GET /activate/MjA1ZjJjOWUtZjJmZC00ZDNlLWI5ZjktMTFiYjJiMzBkYWRm/bb210r-cb574367d34da4d3175ab454a49e6527/ HTTP/1.1” 500 132326
Not sure what’s wrong as this setup already worked in a different project of mine.
Advertisement
Answer
probably you are need force_str
more here: https://docs.djangoproject.com/en/4.1/ref/utils/#django.utils.encoding.force_str
in your case:
JavaScript
1
2
1
user = User.objects.get(pk=uid.decode("utf-8"))
2
more here: https://docs.python.org/3/library/stdtypes.html#bytes.decode