Ошибка при создании токена аутентификации для нового зарегистрированного пользователя в Django Rest Framework

Я работаю над проектом Django, в котором пытаюсь создать auth-токен для только что зарегистрированного пользователя с помощью Django Rest Framework. Однако при запуске функции register я сталкиваюсь со следующей ошибкой:

ValueError: Cannot assign "<User: Test>": "Token.user" must be a "User" instance.

Вот функция регистра, в которой возникает ошибка:

@api_view(['POST'])
def register(request):
    serializer = UserSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()

        user = User.objects.get(username=request.data['username'])
        user.hash_password(request.data['password'])
        user.save()

        token = Token.objects.create(user=user) # This is where the error occurs

        return Response({
            'token': token.key,
            'User': serializer.data
        }, status=status.HTTP_201_CREATED)
    
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Как исправить эту ошибку и успешно создать токен аутентификации для только что зарегистрированного пользователя?

Я попытался зарегистрировать нового пользователя с помощью функции register в моем представлении Django Rest Framework. Я ожидал, что пользователь успешно зарегистрируется (зарегистрируется в базе данных) и что будет сгенерирован токен аутентификации, связанный с этим пользователем.

Ошибка ValueError: Cannot assign "<User: Test>": "Token.user" must be a "User" instance. обычно означает, что объект "пользователь" не является экземпляром модели, которую ожидает поле Token.user.

Ваш код кажется правильным, после serializer.save() возвращаемое значение - экземпляр модели User. Однако hash_password в строке user.hash_password(request.data['password']) не является стандартным методом Django для модели User. Пожалуйста, убедитесь, что этот метод существует в вашей модели User и возвращает экземпляр User, а не строку или что-то еще. Кроме того, этот метод, вероятно, выполняет ту же работу, что и set_password, который уже является частью модели Django User.

Скорее всего, причина в вашем методе hash_password, проверьте его возвращаемый тип и убедитесь, что он возвращает экземпляр User. Также нет необходимости использовать собственный метод хеширования, поскольку встроенный метод set_password обеспечивает ту же функциональность.

Пример того, как это будет выглядеть при использовании set_password:

user.set_password(request.data["password"])
user.save()

Я рекомендую заменить token.objects.create на следующую логику в вашем RegisterView:

from django.urls import reverse
from django.contrib.sites.shortcuts import get_current_site
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from .serializers import RegisterSerializer
from .models import User
from .utils import Util

class RegisterView(generics.GenericAPIView):
    """
    Register a new user with email and password and send verification email (Student or Tutor)
    """

    serializer_class = RegisterSerializer

    def post(self, request):
        user = request.data
        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        user_data = serializer.data
        user = User.objects.get(email=user_data["email"])

        refresh_token = RefreshToken.for_user(user)
        token = str(refresh_token.access_token)

        relative_link = reverse("verify-email")
        current_site = get_current_site(request).domain
        abs_url = "http://" + current_site + relative_link + "?token=" + token

        email_body = "Hi {}! Use the link below to verify your email:\n{}".format(
            user.full_name, abs_url)
        data = {
            "to_email": user.email,
            "email_body": email_body,
            "email_subject": "Verify your email",
        }
        Util.send_email(data)
    return Response(user_data, status=status.HTTP_201_CREATED)

Эта логика позволяет создать пользователя и отправляет письмо для проверки электронной почты. Убедитесь, что в вашем проекте Django настроены необходимые импорты и конфигурации.

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