'How to override the create method for a nested serializer for an APIView post request method?

I am trying to override the create() method for the following Serializer:

serializers.py

class TaggingSerializer(serializers.ModelSerializer):
  tag = TagSerializer()
  resource = ResourceSerializer()
  gameround = GameroundSerializer()
  user = CustomUserSerializer(required=False)

  class Meta:
    model = Tagging
    fields = ('id', 'user', 'gameround', 'resource', 'tag', 'created', 'score', 'origin')

  def create(self, validated_data):
    """Create and return a new tagging"""

    tags_data = validated_data.pop('tags')
    resources_data = validated_data.pop('resources')
    gamerounds_data = validated_data.pop('gamerounds')
    users_data = validated_data.pop('users')
    tagging = Tagging.objects.create(**validated_data)

    for tag_data in tags_data:
      Tag.objects.create(tagging=tagging, **tag_data)

    for resource_data in resources_data:
      Resource.objects.create(tagging=tagging, **resource_data)

    for gameround_data in gamerounds_data:
      Gameround.objects.create(tagging=tagging, **gameround_data)

    for user_data in users_data:
      User.objects.create(tagging=tagging, **user_data)

    return tagging

  def to_representation(self, data):
    data = super().to_representation(data)
    return data

This is the JSON object I am trying to send:

{
        "user": "creator",
        "gameround": 1,
        "resource": 602,
        "tag": "Redtagtestpost",
        "created": "2022-12-12T15:19:49.031000Z",
        "score": 0,
        "origin": ""
    }

However I keep getting various types of "JSON parse..." errors in Postman.

One error I have been getting a lot is:

{"user":{"non_field_errors":["Invalid data. Expected a dictionary, but got str."]},"gameround":{"non_field_errors":["Invalid data. Expected a dictionary, but got int."]},"resource":{"non_field_errors":["Invalid data. Expected a dictionary, but got int."]},"tag":{"non_field_errors":["Invalid data. Expected a dictionary, but got str."]}}

I have tried using different fields for the other models and nothing seems to work.

My suspicion is I somehow need to access data from the request and save it in the right field such as only the username of the user or specify that it is the id of the gameround that is in the JSON that I pass but I don't know how to do this and couldn't find anything about this online.

If I remove the following from the serializer:

tag = TagSerializer()
  resource = ResourceSerializer()
  gameround = GameroundSerializer()
  user = CustomUserSerializer(required=False)

I get the following error:

{"user":["Incorrect type. Expected pk value, received str."],"tag":["Incorrect type. Expected pk value, received str."]}


Solution 1:[1]

Adding this to my serializer solved my issue:

class TaggingSerializer(serializers.ModelSerializer):
  tag_id = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all(),
                                              required=False,
                                              source='tag',
                                              write_only=False)
  resource_id = serializers.PrimaryKeyRelatedField(queryset=Resource.objects.all(),
                                                   required=True,
                                                   source='resource',
                                                   write_only=False)
  gameround_id = serializers.PrimaryKeyRelatedField(queryset=Gameround.objects.all(),
                                                    required=False,
                                                    source='gameround',
                                                    write_only=False)
  user_id = serializers.PrimaryKeyRelatedField(queryset=CustomUser.objects.all(),
                                               required=False,
                                               source='user',
                                               write_only=False)
...

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 CarinaTheBookworm