Django Rest Framework: передать пользователя из представления в сериализатор - PullRequest
2 голосов
/ 18 апреля 2019

У меня есть такой вид для смены пароля пользователя:

class ChangePasswordView(generics.UpdateAPIView):
    serializer_class = ChangePasswordSerializer
    permission_classes = [IsAuthenticated]

        def put(self, request, *args, **kwargs):
            data = request.data.copy()
            data['user'] = self.request.user
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            user = serializer.validated_data['user']
            user.set_password(serializer.validated_data["new_password"])
            user.save()
            return Response(status=status.HTTP_204_NO_CONTENT)

И сериализатор для этого вида выглядит так:

class ChangePasswordSerializer(serializers.Serializer):
    old_password = serializers.CharField()
    new_password = serializers.CharField()
    new_password_retyped = serializers.CharField()

    def validate(self, data):
        old_password = data.get('old_password')
        new_password = data.get('new_password')
        new_password_retyped = data.get('new_password_retyped')
        user = data.get('user')

        # misc validation checks

        data['user'] = user
        return data

и моя проблема в том, что пользовательский объект не передается в сериализатор, попытался распечатать его, чтобы увидеть содержимое данных внутри put:

<QueryDict: {'old_password': ['testpassword'], 'new_password': ['testpassword1'], 'new_password_retyped': ['testpassword1'], 'user': [<User: root>]}>

и внутри сериализатора:

OrderedDict([('old_password', 'testpassword'), ('new_password', 'testpassword1'), ('new_password_retyped', 'testpassword1')])

Как видите, пользователь отсутствует. Сначала я подумал, что это может быть связано с передачей объекта в сериализатор, поэтому я изменил data['user'] = self.request.user на data['user'] = self.request.user.username, чтобы он передавал только строку с именем пользователя, но безуспешно

1 Ответ

4 голосов
/ 18 апреля 2019

Вы не можете передать пользователя сериализатору таким образом, потому что сериализаторы отбрасывают данные, которые не являются релевантными. Попробуйте сделать что-то вроде этого.

class ChangePasswordSerializer(serializers.Serializer):
    old_password = serializers.CharField()
    new_password = serializers.CharField()
    new_password_retyped = serializers.CharField()

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super().__init__(*args, **kwargs)

    def validate(self, data):
        old_password = data.get('old_password')
        new_password = data.get('new_password')
        new_password_retyped = data.get('new_password_retyped')
        user = self.user

        # misc validation checks

        data['user'] = user
        return data

И отдельно передать пользователя сериализатору.

self.get_serializer(data=data, user=self.request.user)
...