使用 django Rest 框架登录

unk*_*own 3 django django-models django-rest-framework

错误看起来就像这样 KeyError: 'user' 而我每次显示此错误消息时都尝试登录。我已经安装了 Django Rest Framework。使用 Rest Framework 登录的最佳方法是什么?

我的看法

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})
Run Code Online (Sandbox Code Playgroud)

我的序列化器

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
Run Code Online (Sandbox Code Playgroud)

bka*_*wan 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

Run Code Online (Sandbox Code Playgroud)

在 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})

Run Code Online (Sandbox Code Playgroud)

如果您想要简单的事情,只需使用 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
        })
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到更多详细信息