Как исправить проблему "detail": "Invalid Token" в django_rest_framework

Я попытался реализовать простой API входа/регистрации с django_rest_framework, используя модуль DRF authToken, и вот мой код : models.py

class User(AbstractUser):
username =models.CharField(max_length=100)
email =models.EmailField('email address', unique=True)
first_name =models.CharField('First Name', max_length=255, blank=True, null=False)
last_name =models.CharField('Last Name', max_length=255, blank=True, null=False)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']

serializers.py

from rest_framework import serializers
from rest_framework.authtoken.models import Token

from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.models import BaseUserManager

User = get_user_model()

class UserLoginSerializer (serializers.Serializer):
    email = serializers.CharField(max_length=300, required=True)
    password = serializers.CharField(required=True, write_only=True)

class AuthUserSerializer(serializers.ModelSerializer):
    auth_token = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id', 'email', 'first_name', 'last_name', 'is_active', 'is_staff')
        read_only_fields = ('id', 'is_active', 'is_staff')

        def get_auth_token(self, obj):
            token = Token.objects.create(user=obj)
            return token.key

class EmptySerializer(serializers.Serializer):
    pass


class UserRegisterSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'email', 'password', 'first_name', 'last_name')

    def validate_email(self, value):    
        user = User.objects.filter(email=value)
        if user:
            raise serializers.ValidationError("Email is already taken ...")
        return BaseUserManager.normalize_email(value) 

    def validate_password(self, value):
        password_validation.validate_password(value)
        return value       


class PasswordChangeSerializer(serializers.Serializer):
    current_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True)

    def validate_current_password(self, value):
        if not self.context['request'].user.check_password(value):
            raise serializers.ValidationError('Current password does not match ...')
        return value

    def validate_new_password(self, value):
        password_validation.validate_password(value)
        return value        

views.py

from django.contrib.auth import get_user_model, logout
from django.core.exceptions import ImproperlyConfigured

from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.parsers import JSONParser


User = get_user_model()

class AuthViewSet(viewsets.GenericViewSet):
    permission_classes = [AllowAny, ]
    serializer_class = serializers.EmptySerializer
    serializer_classes = {
        'login': serializers.UserLoginSerializer,
        'register': serializers.UserRegisterSerializer,
        'password_change': serializers.PasswordChangeSerializer
    }

    @action(methods=['POST', ], detail=False)
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = get_and_authenticate_user(**serializer.validated_data)
        data = serializers.AuthUserSerializer(user).data
        return Response(data=data, status=status.HTTP_200_OK)

    @action(methods=['POST', ], detail=False)
    def register(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = create_user_account(**serializer.validated_data)
        data = serializers.AuthUserSerializer(user).data
        return Response(data=data, status=status.HTTP_201_CREATED)

    @action(methods=['POST', ], detail=False)
    def logout(self, request):
        logout(request)
        data = {'success': 'Successfully logged out ..'}
        return Response(data=data, status=status.HTTP_200_OK)

    @action(methods=['POST'], detail=False, permission_classes=[IsAuthenticated, ])
    def password_change(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        request.user.set_password(serializer.validated_data['new_password'])
        request.user.save()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    def get_serializer_class(self):
        if not isinstance(self.serializer_classes, dict):
            raise ImproperlyConfigured("serializer classes should be a dict mapping")
    
        if self.action in self.serializer_classes.keys():
            return self.serializer_classes[self.action]
        return super().get_serializer_class()

urls.py

urlpatterns = [
    url(r'^register/$', views.AuthViewSet.as_view({'POST': 'register'}), name='register'),
    url(r'^login/$', views.AuthViewSet.as_view({'POST': 'login'}), name='login'),
    url(r'^logout/$', views.AuthViewSet.as_view({'POST': ''}), name='logout'),
]

ожидается формат запроса и ответа (регистр):

{
    "username": "anyusername",
    "password": "passwordfortheusername",
    "first_name": "anyfirstname",
    "last_name": "anylastname",
}


Response
Status: 201 Created
{
    "id": 2
    "first_name": "John",
    "last_name": "Howley",
    "email": "hello@example.com",
    "is_active": true,
    "is_staff": false,
    "is_superuser": false,
    "auth_token": "34303fc8c5a686f2e21b89a3feff4763abab5f7e"
}

login : Запрос

{
    "email": "user@example.com",
    "password": "somepassword"
}

Response
Status: 200 OK
{
    "id": 1,
    "first_name": "anyfirstname",
    "last_name": "anylastname",
    "email": "username@example.com",
    "is_active": true,
    "is_staff": false,
    "is_superuser": false,
    "auth_token": "34303fc8c5a686f2e21b89a3feff4763abab5f7e"
}

но когда я тестирую функцию входа или регистрации, я получаю ответ "detail": "Invalid Token". Я не совсем понял проблему, поэтому мне может понадобиться помощь. спасибо

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