Error creating auth token for newly registered user in Django Rest Framework

28 Views Asked by At

I'm working on a Django project where I'm trying to create an auth token for a newly registered user using Django Rest Framework. However, when running the register function, I run into the following error:

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

Here is the register function where the error occurs:

@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)

How can I fix this error and successfully create the authentication token for the newly registered user?

I have tried to register a new user using the register function in my Django Rest Framework view. I was expecting the user to register successfully (register in the database) and for an auth token to be generated associated with that user.

3

There are 3 best solutions below

0
Malvin Lok On

The ValueError: Cannot assign "<User: Test>": "Token.user" must be a "User" instance. error usually means that the "user" object is not an instance of the model that Token.user field expects.

Your code seems correct, after serializer.save(), the return value is an instance of User model. However, hash_password in line user.hash_password(request.data['password']) is not a standard Django method for User model. Please ensure this method exists in your User model and returns a User instance, not a string or something else. Also, this method probably does the same job as set_password which is already part of the Django User model.

0
Saidi Souhaieb On

It is most likely caused by your hash_password method, check its return type and make sure it returns a User instance. Also no need to use a custom made hashing method as the built in method set_password provides the same functionality.

Example of how it would look like using set_password:

user.set_password(request.data["password"])
user.save()
0
Abdelaziz Naija On

I recommend replacing token.objects.create with the following logic in your 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)

This logic allows you to create a user and sends an email for email verification. Ensure that you have the necessary imports and configurations set up in your Django project.