验证用户帐户在Django Rest Framework中是否处于活动状态

时间:2019-04-04 16:29:09

标签: python django django-rest-framework

我正在尝试通过电子邮件链接实现帐户激活。我的User模型非常简单,继承自django.contrib.auth.models.AbstractUser,因此默认情况下具有is_active字段。注册后,将使用is_active=False参数创建新用户,当用户尝试登录并且即使凭据很好时,我也想处理这种情况,因为帐户未激活,因此不应该登录。我正在使用Knox令牌认证。我的序列化器:

from django.contrib.auth import authenticate
from rest_framework import serializers, exceptions


class LoginUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = ('username', 'password')

    def validate(self, data):
        user = authenticate(**data)
        if user:
            if user.is_active:
                return user
            raise exceptions.AuthenticationFailed('Account is not activated')
        raise exceptions.AuthenticationFailed()

然后查看:

from django.contrib.auth import login
from rest_framework.permissions import AllowAny
from rest_framework.authtoken.serializers import AuthTokenSerializer
from knox.views import LoginView
from .serializers import LoginUserSerializer


class LoginUserView(LoginView):
    serializer_class = LoginUserSerializer
    permission_classes = [AllowAny]

    def post(self, request, *args, **kwargs):
        serializer = AuthTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginUserView, self).post(request)

使用该代码,我偶然发现了一个问题:当我尝试使用已激活的帐户登录时,一切看起来都很好,但是当我尝试未激活的帐户而不是Account is not activated时,我得到了:

{
    "non_field_errors": [
        "Unable to log in with provided credentials."
    ]
}

我认为这是从视图而不是序列化器来的。

1 个答案:

答案 0 :(得分:0)

好的,因此,感谢Shafikur Ra​​hman的建议,我得以使其工作。在尝试使用pdb对其进行调试并在LoginUserSerializer内设置跟踪但什么都没发生后,我意识到在我看来,我不是在指向我写的串行器,而是在指向AuthTokenSerializer。甚至在那之后它仍然不起作用,因为我对django login()和DRF validate()的工作方式缺乏了解。下面的固定代码供参考:

视图:

class LoginUserView(LoginView):
    serializer_class = LoginUserSerializer
    permission_classes = [AllowAny]

    def post(self, request, *args, **kwargs):
        serializer = LoginUserSerializer(data=request.data)  # changed  to desired serializer
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginUserView, self).post(request)

和序列化器:

class LoginUserSerializer(serializers.ModelSerializer):
    username = serializers.CharField()  # added missing fields for serializer
    password = serializers.CharField()

    class Meta:
        model = UserModel
        fields = ('username', 'password')

    def validate(self, data):
        user = authenticate(**data)
        if user:
            if user.is_active:
                data['user'] = user  # added user model to OrderedDict that serializer is validating
                return data  # and in sunny day scenario, return this dict, as everything is fine
            raise exceptions.AuthenticationFailed('Account is not activated')
        raise exceptions.AuthenticationFailed()

另外,为了能够authenticate()非活跃用户,我不得不添加

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.AllowAllUsersModelBackend'
]

在项目设置中。