Python DRF使用序列化程序验证正文并序列化响应

Python DRF使用序列化程序验证正文并序列化响应,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在django中有以下视图,它登录用户并在用户数据使用序列化程序序列化后发回响应 @api_view(['POST']) def sign_in(request): username = request.data['username'] password = request.data['password'] user = authenticate(username=username, password=password) if user is not None

我在django中有以下视图,它登录用户并在用户数据使用序列化程序序列化后发回响应

@api_view(['POST'])
def sign_in(request):
    username = request.data['username']
    password = request.data['password']
    user = authenticate(username=username, password=password)

    if user is not None:
        update_last_login(None, user)  # update the user's last login date
        serializer = UserSignInSerializer(user)
        return Response(serializer.data)

    return Response('Invalid login credentials', status=401)
这个视图中我不喜欢的是直接从主体中提取用户名和密码的方式。我想使用相同的序列化程序来检查主体是否有效。这是可能的还是我必须创建一个新的序列化程序来验证请求?以下是现有的序列化程序:

class UserSignInSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email', 'username', 'profile']
您可以从django rest框架使用。这是一个很好的代码,您可以从中使用。下面我给大家举一个例子:

class LoginSerializer(serializers.Serializer):
    username = serializers.CharField(required=False, allow_blank=True)
    password = serializers.CharField(style={'input_type': 'password'})

    def authenticate(self, **kwargs):
        return authenticate(self.context['request'], **kwargs)

    def _validate_username(self, username, password):
        user = None

        if username and password:
            user = self.authenticate(email=email, password=password)
        else:
            msg = _('Must include "username" and "password".')
            raise exceptions.ValidationError(msg)

        return user

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        user = self._validate_username(username, password)
        if user:
            if not user.is_active:
                msg = _('User account is disabled.')
                raise exceptions.ValidationError(msg)
        else:
            msg = _('Unable to log in with provided credentials.')
            raise exceptions.ValidationError(msg)

        attrs['user'] = user
        return attrs
并在视图中使用此序列化程序:

@api_view(['POST'])
def sign_in(request):
    serializer = LoginSerializer(data=request.data, context={'request': request})
    if serializer.is_valid():
        user = serializer.validated_data['user']
        update_last_login(None, user)  # update the user's last login date
        u_serializer = UserSignInSerializer(user)
        return Response(u_serializer.data)

    return Response(serializer.errors, status=401)

那么答案就是创建一个新的序列化程序?这是否意味着我必须为每个视图创建两个序列化程序?一个用于req,一个用于res?您可以在一个序列化程序中实现它。但是您需要将first_name last name etc设置为只读字段和密码只读字段。但依我看,这样一来,代码就不会干净,一个序列化程序承载了所有。但是有两个具有两个不同目的的序列化程序对我来说似乎更好。这样,您可以保持登录信息和用户信息的不同,并在不影响其他信息的情况下更改其中任何一个。您所说的
是什么意思?这难道不意味着我必须为我拥有的每个视图创建两个序列化器吗?您上面的视图使用两个序列化器。如果req主体包含与responseWell不同的数据,那么我可能必须对所有视图执行此操作,如果请求和响应完全不同,那么最好有两个序列化器。但通常使用一个序列化程序。在这种情况下,正如我前面所说,您可以将它们放在一个。但对于更干净的代码,我使用了两个序列化程序。