0

我正在使用django-rest-knox用户身份验证并knox.auth.TokenAuthentication作为唯一的身份验证类。另外,我通过扩展使用自定义用户模型AbstractBaseUser。我有电子邮件和密码作为登录字段。

根据文档,当您使用令牌身份验证作为唯一的身份验证方法时,您必须覆盖 knox 的内置 LoginView。我遵循了相同的方法,但似乎没有成功。

视图.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)

序列化程序.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")

网址.py

...

urlpatterns = [
    path('login', views.LoginInterestedUserAPI.as_view()),
]

当我转到 url/api/login时,我没有收到电子邮件和密码字段来输入我的凭据并获得以下输出:-

"detail": "Authentication credentials were not provided."
4

2 回答 2

1

第一个问题AuthTokenSerializerviews.py. AuthTokenSerializer使用用户名和密码登录,而我的自定义用户模型使用电子邮件和密码。第二个问题是LoginInterestedUserSerializer我在其中使用ModelSerializer并因此继承了create方法,因此我得到了错误user with this email already exists。因此,serializers.Serializer应该使用。以下是工作代码片段:-

序列化程序.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")

视图.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]
        })
于 2019-06-04T07:01:41.440 回答
1

我已经以专业的方式解决了这个问题。上面提到的方法对你有用,但现在我要和你分享一个专业的方法。因此,您必须按照步骤操作。

步骤1:首先,创建一个用于登录的序列化程序。但是继承 Serializer 类,而不是 ModelSerialzer 类。

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 框架。因此,如果您使用任何其他库/框架,您的方法可能会有所不同。

于 2021-06-16T06:04:53.690 回答