Sreekar Mouli
Sreekar Mouli

Reputation: 1432

Django - How can I do PATCH requests - ModelSerializer, RetrieveUpdateDestroyAPIView

I have a ProfileSerializer which is a ModelSerializer:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email', 'password')

class ProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = User.objects.create_user(**user_data, username=validated_data.get('username'))
        profile = Profile.objects.create(user=user, **validated_data)
        return profile

    def update(self, instance, validated_data):
        instance.dob = validated_data.get('dob', instance.dob)
        instance.karma = validated_data.get('karma', instance.karma)
        instance.username = validated_data.get('username', instance.username)
        user_data = validated_data.pop('user')
        instance.user.first_name = user_data.get('first_name', instance.user.first_name)
        instance.user.last_name = user_data.get('last_name', instance.user.last_name)
        instance.user.email = user_data.get('email', instance.user.email)
        instance.user.username = instance.username
        new_password = user_data.get('password')
        if new_password:
            instance.user.set_password(new_password)
        instance.user.save()
        instance.save()
        return instance

    class Meta:
        model = Profile
        fields = '__all__'

And, I have a view named DetailProfile which is a RetrieveUpdateDestroyAPIView:

class DetailProfile(RetrieveUpdateDestroyAPIView):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer
    lookup_field = 'username'
    lookup_url_kwarg = 'username'

The problem with this is whenever I do a PUT request, I have to send all the fields including password. Now, the password that I obtain from GET request is hashed. So, If I send the same hashed password in PUT request, the password is getting replaced with that string (which looks something like this pbkdf2_sha256$100000$v7HiZeWnhmQj$ftiQyZCjMJ6pa26P5w72wQZvn+goEB94/lKyJ8LeKrM=).

So, I want to make a PATCH request and not send password.

Upvotes: 2

Views: 1160

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47354

You can just override put method and add partial argument, this enable partial update logic:

class DetailProfile(RetrieveUpdateDestroyAPIView):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer
    lookup_field = 'username'
    lookup_url_kwarg = 'username'

    def put(self, request, *args, **kwargs):
        kwargs['partial'] = True 
        return self.update(request, *args, **kwargs)

BTW patch request is also available for RetrieveUpdateDestroyAPIView. So if you need PUT and PATCH at the same time you can use them without overriding put() method.

Upvotes: 3

Related Questions