无法使用令牌身份验证作为具有自定义用户模型的 django-rest-knox 中的唯一身份验证 class
Unable to use token authentication as the only authentication class in django-rest-knox with custom user model
我正在使用 django-rest-knox
进行用户身份验证,并将 knox.auth.TokenAuthentication
作为唯一的身份验证 class。此外,我通过扩展 AbstractBaseUser
使用自定义用户模型。我有电子邮件和密码作为登录字段。
根据文档,当您使用令牌身份验证作为唯一的身份验证方法时,您必须覆盖 knox 的内置登录视图。我用了同样的方法,但似乎没有用。
views.py
class LoginInterestedUserAPI(LoginView):
def get_user_serializer_class(self):
return LoginInterestedUserSerializer
def post(self, request, format=None):
serializer = AuthTokenSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return super(LoginInterestedUserAPI, self).post(request, format=None)
serializers.py
class LoginInterestedUserSerializer(serializers.ModelSerializer):
class Meta:
model = InterestedUser
fields = ('email', 'password')
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Unable to log in with the provided credentials")
urls.py
...
urlpatterns = [
path('login', views.LoginInterestedUserAPI.as_view()),
]
当我转到 url /api/login
时,我没有收到用于输入我的凭据的电子邮件和密码字段,也没有收到以下输出:-
"detail": "Authentication credentials were not provided."
第一期在 AuthTokenSerializer
中 views.py
。 AuthTokenSerializer
使用用户名和密码登录,而我的自定义用户模型使用电子邮件和密码。第二个问题是在 LoginInterestedUserSerializer
中,我在其中使用了 ModelSerializer
,因此继承了 create
方法,因此我得到了错误 user with this email already exists
。因此,应该使用serializers.Serializer
。以下是工作代码片段:-
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = InterestedUser
fields = ('full_name', 'email')
class LoginInterestedUserSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField(max_length=128)
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Unable to log in with the provided credentials")
views.py
class LoginView(GenericAPIView):
serializer_class = LoginInterestedUserSerializer
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
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
我已经以专业的方式解决了这个问题。上面的方法对你有用,我已经提到了,但现在我要和你分享一个专业的方法。因此,您必须按照步骤进行操作。
第一步:
首先,创建一个用于登录的序列化程序。但是继承Serializerclass,而不是ModelSerialzerclass.
class LoginSerializer(serializers.Serializer):
# We're using custom model fields
email = serializers.CharField()
password = serializers.CharField()
def validate(self,data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Incorrect credentials!")
第 2 步:
现在在您的 views.py 文件中创建一个登录名 API。
# Login API
class LoginView(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self,request,*args,**kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data
return Response({
"user": AccoutSerilizer(user,context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
第 3 步:
现在只需在 urls.py 文件中创建登录 API 的端点。但请记住,我使用的是 Django 的 Knox 框架。因此,如果您使用任何其他 library/framework,您的方法可能会有所不同。
我正在使用 django-rest-knox
进行用户身份验证,并将 knox.auth.TokenAuthentication
作为唯一的身份验证 class。此外,我通过扩展 AbstractBaseUser
使用自定义用户模型。我有电子邮件和密码作为登录字段。
根据文档,当您使用令牌身份验证作为唯一的身份验证方法时,您必须覆盖 knox 的内置登录视图。我用了同样的方法,但似乎没有用。
views.py
class LoginInterestedUserAPI(LoginView):
def get_user_serializer_class(self):
return LoginInterestedUserSerializer
def post(self, request, format=None):
serializer = AuthTokenSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return super(LoginInterestedUserAPI, self).post(request, format=None)
serializers.py
class LoginInterestedUserSerializer(serializers.ModelSerializer):
class Meta:
model = InterestedUser
fields = ('email', 'password')
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Unable to log in with the provided credentials")
urls.py
...
urlpatterns = [
path('login', views.LoginInterestedUserAPI.as_view()),
]
当我转到 url /api/login
时,我没有收到用于输入我的凭据的电子邮件和密码字段,也没有收到以下输出:-
"detail": "Authentication credentials were not provided."
第一期在 AuthTokenSerializer
中 views.py
。 AuthTokenSerializer
使用用户名和密码登录,而我的自定义用户模型使用电子邮件和密码。第二个问题是在 LoginInterestedUserSerializer
中,我在其中使用了 ModelSerializer
,因此继承了 create
方法,因此我得到了错误 user with this email already exists
。因此,应该使用serializers.Serializer
。以下是工作代码片段:-
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = InterestedUser
fields = ('full_name', 'email')
class LoginInterestedUserSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField(max_length=128)
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Unable to log in with the provided credentials")
views.py
class LoginView(GenericAPIView):
serializer_class = LoginInterestedUserSerializer
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
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
我已经以专业的方式解决了这个问题。上面的方法对你有用,我已经提到了,但现在我要和你分享一个专业的方法。因此,您必须按照步骤进行操作。
第一步: 首先,创建一个用于登录的序列化程序。但是继承Serializerclass,而不是ModelSerialzerclass.
class LoginSerializer(serializers.Serializer):
# We're using custom model fields
email = serializers.CharField()
password = serializers.CharField()
def validate(self,data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError("Incorrect credentials!")
第 2 步: 现在在您的 views.py 文件中创建一个登录名 API。
# Login API
class LoginView(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self,request,*args,**kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data
return Response({
"user": AccoutSerilizer(user,context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
第 3 步: 现在只需在 urls.py 文件中创建登录 API 的端点。但请记住,我使用的是 Django 的 Knox 框架。因此,如果您使用任何其他 library/framework,您的方法可能会有所不同。