15

I'm getting the above error when creating token, here's the code:

from rest_framework import generics, permissions
from rest_framework.response import Response 
from knox.models import AuthToken
from .serializers import UserSerializer, RegisterSerializer

class RegisterAPI(generics.GenericAPIView):
    serializer_class = RegisterSerializer

def post(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = serializer.save()
    return Response({
        "user": UserSerializer(user, context=self.get_serializer_context()).data,
        "token": AuthToken.objects.create(user)
    })

what am I doing wrong here

kzrfaisal
  • 1,355
  • 5
  • 15
  • 26
  • 1
    Well you will need to serialize the `AuthToken` as well, like you did with the user (or pass an attribute of that token that can be converted to JSON (like a `str`, `int`, etc.). An `AuthToken` itself is, at least not without some extra logic, serializable). – Willem Van Onsem Apr 13 '19 at 17:59
  • How to serialize AuthToken ? – kzrfaisal Apr 13 '19 at 18:39
  • With a serializer, just like you did with the `UserSerializer`. – Willem Van Onsem Apr 13 '19 at 18:42
  • 1
    ok, got it, it's a tuple which can't be serialized, doing this worked AuthToken.objects.create(user)[1]. – kzrfaisal Apr 13 '19 at 19:03
  • 2
    This seems to be a change in `django-rest-knox`. I have a project with `django-rest-know v 3.6.0` using the code you have in the post. I'm just starting an new project (using version 4.0.1), and I've had to add the `[1]` to the token serialization. – HenryM Apr 15 '19 at 12:15

3 Answers3

47

The Token.objects.create returns a tuple (instance, token). So in order to get token use the index 1

"token": AuthToken.objects.create(user)[1]

Rasika Weragoda
  • 936
  • 14
  • 15
  • 1
    But is that the real token which we need to work with. What i mean is when we print AuthToken.objects.create(user) it gives output like this; (, 'another_token') and when i checked the database, the "long_token" is stored in the database not the "another_token" but the method you are using returns "another_token". – Irfan wani May 20 '21 at 11:17
15

Better way is use this method in python

_, token = AuthToken.objects.create(user)
return Response({
    "user": UserSerializer(user, context=self.get_serializer_context()).data,
    "token": token
})
Radesh
  • 13,084
  • 4
  • 51
  • 64
2

This particular error occurs because the Token.objects.create returns a tuple (instance, token). just use the second position [1] by using instead of former

"token": AuthToken.objects.create(user)[1]
raven404
  • 1,039
  • 9
  • 14