Django, проблема активации пользователя на сайте при переходе по ссылке в письме после регистрации

столкнулся с проблемой проверки email пользователя после регистрации и активации пользователя при переходе по ссылке из email. Суть -Пользователь создается с значением is_active = False, email отправляется, переходим по ссылке и должен пользователь стать активным (is_active = True), но увы... не проходит проверку в строке if default_token_generator.check_token(user, token):...

views:

class RegisterView(CreateView):
    form_class = RegisterUserForm
    template_name = "registration/reg.html"
    success_url = "reg-done"

    def form_valid(self, form):
        user = form.save(commit=False)
        user.is_active = False
        user.save()  # Сохраните пользователя в базе данных

        token = default_token_generator.make_token(user)
        print(f"Generated token: {token}")  # Запись токена в консоль
        self.send_confirmation_email(user, token)

        return super().form_valid(form)

    def send_confirmation_email(self, user, token):
        print(f"User PK: {user.pk}")  # Запись PK пользователя в консоль
        uid = urlsafe_base64_encode(force_bytes(user.pk))
        print(f"uid: {uid}")
        current_site = get_current_site(self.request)
        mail_subject = "Активируйте свой аккаунт"
        message = render_to_string(
            "registration/acc_active_email.html",
            {
            "user": user,
            "domain": current_site.domain,
            "uid": uid,
            "token": token,
            },
        )
        email = EmailMultiAlternatives(mail_subject, message, to=[user.email])
        email.attach_alternative(message, "text/html")
        email.send()

def activate(request, uidb64, token):
try:
    uid = force_str(urlsafe_base64_decode(uidb64))
    print(f"Encoded uid: {uid}")  # Запись закодированного uid в консоль
    user = get_user_model().objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, get_user_model().DoesNotExist):
    user = None
    print("попали в exept и user теперь None")

if user is not None:
    print(user, token)
    print(uid)
    if default_token_generator.check_token(user, token):
        print(f"токен при активации:", token)
        user.is_active = True
        user.save()
        return redirect("login")
    else:
        print(uid)
        print(f"else1 токен при активации:", token)
        print(f"else1 юзер при активации:", user)
        return render(request, "registration/activation_invalid.html")
else:
    print(f"else2 токен при активации:", token)
    return render(request, "registration/activation_invalid.html")

При переходе по ссылке в письме попадаем на страничку activation_invalid.html, минуя if default_token_generator.check_token(user, token): - попадаем в else... Токены вроде совпадают, консоль выдает:

Generated token: c3mqrl-bb20a6f3280fd2176676ec33f5f631ba
User PK: 22
uid: MjI

[09/Mar/2024 16:21:23] "GET /users/reg-done HTTP/1.1" 301 0 Encoded uid: 22 test2 c3mqrl-bb20a6f3280fd2176676ec33f5f631ba else1 токен при активации: c3mqrl-bb20a6f3280fd2176676ec33f5f631ba [09/Mar/2024 16:22:40] "GET /users/activate/MjI/c3mqrl-bb20a6f3280fd2176676ec33f5f631ba/ HTTP/1.1" 200 12465 Ну и пользователь не активируется. Все перепробовал, даже ии не смог разобраться, подскажите пожалуйста в чем может быть проблема?

В общем разобрался! Может кому понадобится: Оказалось, если вызвать ошибку в функции отправки email и не дать перейти на новую страницу (типа регистрация успешна), то ссылка работать будет и соответственно пользователь активируется. То есть, при обновлении или переходе на страницу (любую) сразу при регистрации пользователь каким-то образом меняется и токен активации уже не действует. По этому я решил эту проблему следующим способом:

class RegisterView(CreateView):
  form_class = RegisterUserForm
  template_name = "registration/reg.html"

  def form_valid(self, form):
    with transaction.atomic():
        user = form.save(commit=False)
        user.is_active = False
        user.save()  # Сохраните пользователя в базе данных

        token = default_token_generator.make_token(user)
        print(f"Generated token: {token}")  # Запись токена в консоль
        self.send_confirmation_email(user, token)

    messages.success(
        self.request,
        "Регистрация прошла успешно! Пожалуйста, проверьте свою электронную почту для активации учетной записи.",
    )
    return HttpResponseRedirect(
        reverse("home")
    )

def send_confirmation_email(self, user, token):
    print(f"User PK: {user.pk}")  # Запись PK пользователя в консоль
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    print(f"uid: {uid}")
    current_site = get_current_site(self.request)
    mail_subject = "Активируйте свой аккаунт"
    message = render_to_string(
        "registration/acc_active_email.html",
        {
            "user": user,
            "domain": current_site.domain,
            "uid": uid,
            "token": token,
        },
    )
    email = EmailMultiAlternatives(mail_subject, message, to=[user.email])
    email.attach_alternative(message, "text/html")
    email.send()

Пришлось использовать "HttpResponseRedirect" до отправки email со ссылкой на активацию. Убрал строку "success_url = "reg-done"" соответственно. И всё замечТательно работает ))) Спасибо огромное Вам @strawdog за то, что Вы отозвались и помогли. Как все вышло -- я написал код, чтобы вновь проверить всё print-ами и вышло что допустил ошибку:

    def send_confirmation_email(self, user, token):
    print(f"User PK: {user.pk}")  # Запись PK пользователя в консоль
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    print(f"uid: {uid}")
    current_site = get_current_site(self.request)
    mail_subject = "Активируйте свой аккаунт"
    message = render_to_string(
        "registration/acc_active_email.html",
        {
            "user": user,
            "domain": current_site.domain,
            "uid": uid,
            "token": token,
        },
    )
    email = EmailMultiAlternatives(mail_subject, message, to=[user.email])
    email.attach_alternative(message, "text/html")
    email.send()
    print("token во время отправки: " + token) # ошибка Конкатенации строк
    print("user во время отправки: " + str(user))

Что и привело меня к ответу ))) Надеюсь кому-то понадобится, а то я неделю потратил на эту вроде как очевидную вещь, но не совсем понятную сразу.

Вернуться на верх