Home > Net >  KeyError: 'user_id' when using PUT request
KeyError: 'user_id' when using PUT request

Time:10-01

Recently started working with Django REST framework. I have a user table and another table that stores some relevant data for each user. I've set up POST/GET/DELETE methods fine, but I can't get the method for perform_update working - I keep getting a KeyError at /api/sdgdata/1 'user_id' error in Postman when I attempt a put request for a user. Plz see code below:

Models:

class TestDataTwo(models.Model):
    user = models.ForeignKey("auth.User", related_name="testdatatwo", on_delete=models.CASCADE)
    test_name = models.CharField(max_length=1024, null=True, default="N/A")

Serializers:

class TestDataTwoSerializer(serializers.ModelSerializer):

    class Meta:
        model = TestDataTwo
        fields = (
            "id",
            "test_name",
        )

    def update(self, instance, validated_data):

        # get user id from validated data:
        user_id = validated_data.pop('user_id')

        # get user:
        user = User.objects.get(id=user_id)

        # set user on instance:
        instance.user = user
        instance.save()

        # continue with update method:
        super().update(instance, validated_data)

Views:

class TestDataTwoViewSet(ModelViewSet):
    queryset = TestDataTwo.objects.all().order_by('id')
    serializer_class = TestDataTwoSerializer
    paginator = None

    # CREATE NEW TESTDATATWO ROW FOR USER
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    # GET ALL ENTRIES OF TESTDATATWO FOR SPECIFIC USER, EXCEPT IF SUPERUSER, THEN RETURN ALL
    def get_queryset(self):
        # if self.request.user.is_superuser:
        #     return self.queryset
        # else:
        return self.queryset.filter(user=self.request.user)

    def perform_update(self, serializer):
        instance = self.get_object()
        serializer.save(user=self.request.user)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # DELETE TESTDATATWO ID
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

Postman GET:

Get

Postman PUT:

PUT

I've tried a number of variations on the perform_update method, but I am guessing I am missing a reference to the user's user_id somehow...Appreciate any help.

CodePudding user response:

This error is caused by validated_data.pop('user_id'), since user_id was not defined as a field on the serializer nor was it passed in the request data. It seems you are aiming to save the current user as the user field of the TestDataTwo instance being updated.

In that case you don't need to override update, since saving the user based on self.request.user on a TestDataTwo instance is already done by the serializer's save here:

def perform_update(self, serializer):
    serializer.save(user=self.request.user)

This means that you don't have to do any processing in the serializer anymore, so it can be just:

class TestDataTwoSerializer(serializers.ModelSerializer):
    class Meta:
        model = TestDataTwo
        fields = ("id", "test_name",)

    # No need to override update for saving self.request.user to `TestDataTwo`'s user

For more information on this functionality, you can have a read here..[DRF-docs-Passing-additional-attributes-to-save].

  • Related