Как исправить проблему "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". Я не совсем понял проблему, поэтому мне может понадобиться помощь. спасибо