'Why Model Serializer is saving partial data?

class CreateWithIpMixin:
    def create(self, request, *args, **kwargs):
        created_by = request.user.id
        created_by_ip = request.META.get("REMOTE_ADDR")
        #############
        creator_info = {'created_by': created_by, "created_by_ip": created_by_ip}
        data = {**request.data, **creator_info}
        serializer = self.get_serializer(data=data)
        #############
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

request.data = {'name': 'Delhi', 'display_name': 'Delhi', 'short_code': 'DL', 'is_approved': True}

data = {'name': 'Delhi', 'display_name': 'Delhi', 'short_code': 'DL', 'is_approved': True, 'created_by': 4, 'created_by_ip': '127.0.0.1'}

I'm passing complete data in the serializer but only getting request.data in my Serializer (validate method). The other two fields 'created_by' , 'created_by_ip' is present in my model but I want to fill these column automatically that's why I have not mentioned it in serializer fields , also I don't want to return it after saving the data.

Serializer.py

class StateSerializer(serializers.ModelSerializer):
    class Meta:
        model = States
        fields = [
            "id",
            "name",
            "display_name",
            "short_code",
        ]

    def validate(self, attrs):
        print(attrs, "Attrs")
        return super().validate(attrs)


Solution 1:[1]

I don't understand why you don't want to include those fields if serializer if you are passing creator_info to fill them.

If you don't mention those fields in fields then they will be discarded at serializer validation.

Ow. I get it I think. If you want to remove some fields from serializer then you have few options.

  1. Split serializers

Make CreateStateSerializer that will take all fields needed. Make ReturnStateSerializer that will return just the data you want to return.

Then just do something like:

creator_info = {'created_by': created_by, "created_by_ip": created_by_ip}
data = {**request.data, **creator_info}

create_serializer = CreateStateSerializer(data=data)
create_serializer.is_valid(raise_exception=True)
create_serializer.save()

return_serializer = ReturnStateSerializer(**create_serializer.data)
return_serializer.is_valid(raise_exception=True)
  1. pop() fields from serializer data

    serializer.pop("created_by")
    serializer.pop("created_by_ip")

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1