So I have the following token activation setup for users to activate their accounts
# urls.py # Activation path('activate/<uidb64>/<token>/', user_views.activate, name='activate'),
# views.py User = get_user_model() # Get custom user model def activate(request, uidb64, token): # Debugging uid = force_bytes(urlsafe_base64_decode(uidb64)) print(User.objects.get(pk=uid)) try: uid = force_bytes(urlsafe_base64_decode(uidb64)) user = User.objects.get(pk=uid) except (TypeError, ValueError, OverflowError, User.DoesNotExist): user = None if user is not None and account_activation_token.check_token(user, token): user.is_active = True user.email_confirmed = True user.save() login(request, user) return redirect('/dashboard/overview/') else: return render(request, 'user/authentication/account_activation_invalid.html')
# tokens.py from django.contrib.auth.tokens import PasswordResetTokenGenerator import six class AccountActivationTokenGenerator(PasswordResetTokenGenerator): def _make_hash_value(self, user, timestamp): return ( six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.email_confirmed) ) account_activation_token = AccountActivationTokenGenerator()
# models.py # Custom usermodel class UserProfile(AbstractBaseUser, PermissionsMixin): # Unique identifier id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # Email and name of the user email = models.EmailField(max_length=255, unique=True) name = models.CharField(max_length=255) # Privilege and security booleans is_staff = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) is_active = models.BooleanField(default=False) email_confirmed = models.BooleanField(default=False) objects = UserProfileManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] def email_user(self, subject, message, from_email=None, **kwargs): """Send mail to user - Copied from original class""" send_mail(subject, message, from_email, [self.email], **kwargs) def __str__(self): return self.email
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:
user = User.objects.get(pk=uid.decode("utf-8"))
more here: https://docs.python.org/3/library/stdtypes.html#bytes.decode