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.
CodePudding user response:
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