Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: pass user from view to serializer

I have such view for user change password:

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)

And serializer for this view looks like this:

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

and my problem is that user object is not being passed to serializer, tried printing it to see content of data inside put:

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

and inside serializer:

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

As you can see, user is missing. First, I thought that it may have something to do with passing object to serializer so I changed data['user'] = self.request.user to data['user'] = self.request.user.username so it would only pass string with username, but with no luck

like image 741
PotatoBox Avatar asked Apr 18 '19 16:04

PotatoBox


People also ask

How to pass extra data to a Django REST framework serializer?

In this post, you will learn how to Pass Extra Data to a Django REST Framework Serializer and Save it to the Database. In a standard Django form, a code snippet of the procedure would look like this: form = VoterForm (request.POST) if form.is_valid (): voter = form.save (commit=False) voter.user = request.user voter.save ()

How to validate the data in Django REST framework?

Serializers are used to validate the data in Django rest framework. Generally, serializers provide basic validations based on the type of field. Model serializers use model validations (primary key, foreign key, unique, etc). We not only use these basic validations but also custom validations to some of the fields.

How do serializers work in the rest framework?

The serializers in REST framework work very similarly to Django's Form and ModelForm classes. We provide a Serializer class which gives you a powerful, generic way to control the output of your responses, as well as a ModelSerializer class which provides a useful shortcut for creating serializers that deal with model instances and querysets.

How to write views in Django REST-framework?

Now we can use the serializers to write views. Django Rest-Framework supports two different types of views. We’ll use ViewSets (Class Based Views). ViewSets works exactly same as Generic Views. The only difference is using ViewSet you don’t have to create separate views for getting list of objects and detail of one object.


1 Answers

You cannot pass user to serializer this way because serializers drop data which is not relevent. Try doing something like this.

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

And pass user to serializer separately.

self.get_serializer(data=data, user=self.request.user)
like image 158
Nafees Anwar Avatar answered Nov 15 '22 04:11

Nafees Anwar