Mark
Mark

Reputation: 109

How to update user and profile properly in django rest framework?

Here I am trying to update user and user_profile model.This updates the user but the one problem with this is: If I don't provide the address or any other field then it becomes blank after updating.How can I solve this ?

If i update only one field then it makes other field null while updating.I want to store the user's previous data if user doesn't update the field

models.py

class Profile(models.Model):
    user = models.OneToOneField(get_user_model(),on_delete=models.CASCADE,related_name='profile')
    address = models.CharField(max_length=250,blank=True,null=True)

serializer.py

class UpdateUserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()
    class Meta:
        model = get_user_model()
        fields = ['first_name', 'last_name', 'profile']

    def update(self, instance, validated_data):
        instance.username = validated_data.get('username', instance.username)
        instance.email = validated_data.get('email', instance.email)
        instance.first_name = validated_data.get('first_name', instance.first_name)
        instance.last_name = validated_data.get('last_name', instance.last_name)
        instance.save()
        profile_data = validated_data.pop('profile')
        instance.profile.address = profile_data.get('address', instance.profile.address)
        instance.profile.save()

        return instance

views.py

class UpdateUser(generics.UpdateAPIView):
    serializer_class = UpdateUserSerializer
    queryset = get_user_model().objects.all()

Upvotes: 2

Views: 4586

Answers (1)

Gasanov
Gasanov

Reputation: 3399

You are overriding model instance fields on update with values from params. If there are no corresponding params, you will get empty strings as values.

DRF comes with this logic already implemented. You only have to process profile data. Change serializers.py to:

class UpdateUserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()
    class Meta:
        model = get_user_model()
        fields = ['first_name', 'last_name', 'profile']

    def update(self, instance, validated_data):
        # We try to get profile data
        profile_data = validated_data.pop('profile', None)
        # If we have one
        if profile_data is not None:
            # We set address, assuming that you always set address
            # if you provide profile
            instance.profile.address = profile_data['address']
            # And save profile
            instance.profile.save()
        # Rest will be handled by DRF
        return super().update(instance, validated_data)

Make sure you use PATCH request, as PUT is for whole instance update. PATCH is for partial instance update.

Upvotes: 4

Related Questions