我正在尝试通过电子邮件链接实现帐户激活。我的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."
]
}
我认为这是从视图而不是序列化器来的。
答案 0 :(得分:0)
好的,因此,感谢Shafikur Rahman的建议,我得以使其工作。在尝试使用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'
]
在项目设置中。