如何在序列化器 class 上获取经过身份验证的用户进行验证

How to get authenticated user on serializer class for validation

我正在使用 django-rest-framework 开发一个项目。在我的 API 视图中,经过身份验证的用户可以创建其他用户。但是,只有五个。然后,如果一个用户注册了五个用户,我想在达到限制的响应中发送给他。然后,我需要让经过身份验证的用户进入我的序列化程序,但是我找不到将它从我的 ModelViewSet 传递到我的序列化程序的方法。

这是我的代码:

查看:

class ChildUserViewSet(viewsets.ModelViewSet):
    serializer_class = ChildUserSerializer
    queryset = User.objects.all()

    authentication_classes = (
        TokenAuthentication,
    )
    permission_classes = (
        IsAuthenticated,
    )

    def perform_create(self, serializer):
        account_group = self.request.user.userprofile.get_account_group

        mobile_number = serializer.data.get('mobile_number')
        password = serializer.data.get('password')
        user = serializer.save()
        user.set_password(password)
        user.save()

        # Generate user profile
        UserProfile.objects.create(
            user=user,
            mobile_number=mobile_number,
            user_type=CHILD,
            related_account_group=account_group,
        )

序列化器:

class ChildUserSerializer(serializers.ModelSerializer):
    mobile_number = serializers.CharField()

    class Meta:
        model = User

        fields = (
            'first_name',
            'last_name',
            'email',
            'password',
            'mobile_number',
        )

    def validate(self, data):
        """
        Check that the start is before the stop.
        """
        # Get authenticated user for raise hit limit validation



    def validate_email(self, value):
        if User.objects.filter(email=value):
            raise serializers.ValidationError("This field must be unique.")
        return value

    def create(self, validated_data):
        username = generate_unique_username(
            u'{0}{1}'.format(
                validated_data['first_name'],
                validated_data['last_name'],
            )
        )

        user = User(
            username=username,
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name'],
            email=validated_data['email'],
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

然后,在我的序列化程序的 def validate(self, data) 函数中,我想获取当前经过身份验证的用户。

如何将 request.user 从我的 API 视图传递到我的序列化程序?

您可以使用 serializer = ChildUserSerializer(data, context={'request': request}) 将额外的上下文传递给您的序列化程序。然后,您可以在序列化程序验证方法中通过 request.user 访问经过身份验证的用户。

在您初始化序列化器时的视图中,如

serializer = ChildUserSerializer(data=request.DATA,context={'request':request})

,在函数调用

内的序列化程序中发送包含 request.Then 的上下文

request=self.context['request']

然后就可以访问request.user.

我找到了一个更简单的方法来完成这个!事实证明,Rest Framework 的 GenericAPIView 基础 class(所有 Rest Framework 的通用 View classes 都从中继承)includes a function called get_serializer_context():

def get_serializer_context(self):
    """
    Extra context provided to the serializer class.
    """
    return {
        'request': self.request,
        'format': self.format_kwarg,
        'view': self
    }

如您所见,返回的 context 对象包含视图接收到的相同 request 对象。然后设置此对象 when the serializer is initialized:

def get_serializer(self, *args, **kwargs):
    """
    Return the serializer instance that should be used for validating and
    deserializing input, and for serializing output.
    """
    serializer_class = self.get_serializer_class()
    kwargs['context'] = self.get_serializer_context()
    return serializer_class(*args, **kwargs)

因此,要访问发出请求的用户,您只需在序列化程序的 validate_ 函数中调用 self.context['request'].user

class TemplateSerializer(serializers.ModelSerializer):
    def validate_parent(self, value):
        print(self.context['request'].user)

        return value

    class Meta:
        model = Template

最棒的是,您不必覆盖 ModelViewSet 中的任何内容,它们可以像您希望的那样保持简单:

class TemplateViewSet(viewsets.ModelViewSet):
    serializer_class = TemplateSerializer
    permission_classes = [IsAdmin]

在 djangorestframework > 3.2.4 中,rest_framework.generic.GenericAPIView class 在序列化程序上下文中默认包含 http 请求。

因此在您的序列化程序中,您可以通过以下方式访问它:self.context['request'] 和用户 self.context['request'].user

因此您的 ChildUserSerializer 将如下所示:

class ChildUserSerializer(serializers.ModelSerializer):
    mobile_number = serializers.CharField()
    ....
    def validate(self, data):
        """
        Check that the start is before the stop.
        """
        # Get authenticated user for raise hit limit validation
        user = self.context['request'].user
        # do something with the user here
    def validate_email(self, value):
        if User.objects.filter(email=value):
            raise serializers.ValidationError("This field must be unique.")
        return value
    ...