使用Django Rest Framework登录

3

当我尝试登录时,错误信息看起来像是这样的 KeyError: 'user'。 我已经安装了Django Rest Framework。使用Rest框架进行登录的最佳方法是什么?

我的视图代码:

class LoginAPIView(APIView):

    def post(self, request):
        serializer = LoginSerializers(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        token, created = Token.objects.get_or_create(user=user)
        return Response({"status": status.HTTP_200_OK, "Token": token.key})

我的序列化器
class LoginSerializers(serializers.Serializer):
    class Meta:
        model = User

        email = serializers.CharField(max_length=255)
        password = serializers.CharField(max_length=128, write_only=True)

    def validate(self, data):
        email = data.get('email', None)
        password = data.get('password', None)
        if email and password:

            user = authenticate(username=email, password=password)
            if user:
                data['user'] = user

            data['user'] = user
        return data

2
为什么在validate中要返回user - dirkgroten
那是我的一个错误。在从验证中删除返回用户后,我只能登录一个用户,即超级用户。 - unknown
1
你的验证方法从未引发过验证错误,但如果userNone,它应该引发错误。除此之外,它应该可以正常工作。如果只有超级用户可以登录,那么你可能需要检查一下如何创建用户。 - dirkgroten
1个回答

5

您没有引发ValidationError异常。 您需要重构您的序列化器,并在没有用户实例时引发验证错误。

from django.contrib.auth import authenticate, get_user_model
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers

User = get_user_model()


class LoginSerializers(serializers.Serializer):
    email = serializers.CharField(max_length=255)
    password = serializers.CharField(
        label=_("Password"),
        style={'input_type': 'password'},
        trim_whitespace=False,
        max_length=128,
        write_only=True
    )

    def validate(self, data):
        username = data.get('email')
        password = data.get('password')

        if username and password:
            user = authenticate(request=self.context.get('request'),
                                username=username, password=password)
            if not user:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = _('Must include "username" and "password".')
            raise serializers.ValidationError(msg, code='authorization')

        data['user'] = user
        return data


在 LoginAPIView 中,您应该删除 login(request,user),并改为使用 update_last_login(None,user)。
class LoginAPIView(APIView):
    def post(self, request, *args, **kwargs):
        serializer = LoginSerializers(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        update_last_login(None, user)
        token, created = Token.objects.get_or_create(user=user)
        return Response({"status": status.HTTP_200_OK, "Token": token.key})

如果你想要简单的东西,只需使用Django Rest Framework提供的内置身份验证功能。

from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response

class CustomAuthToken(ObtainAuthToken):

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user_id': user.pk,
            'email': user.email
        })

你可以在此处找到更多详细信息:这里

什么是update_last_login? - Amugae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接