Home > Net >  How to get all data associate with serializers.PrimaryKeyRelatedField
How to get all data associate with serializers.PrimaryKeyRelatedField

Time:09-18

I am trying to get all the data associated with this interest_category serializer. This is what I am currently getting:

{
        "project_title": "Dogs",
        "project_description": "and cats",
        "interest_category": [
            4,
            7
        ],
        "created_by": 1,
        "created_at": "2022-09-17T04:31:40.884357Z",
        "updated_at": "2022-09-17T04:31:40.884357Z"
    },

What I am trying to get:

{
        "project_title": "Dogs",
        "project_description": "and cats",
        "interest_category": [
            {
                "id": 4,
                "interest_name": "Test"
            },
            {
                "id": 7,
                "interest_name": "Business"
            }
        ],
        "created_by": 1,
        "created_at": "2022-09-17T04:31:40.884357Z",
        "updated_at": "2022-09-17T04:31:40.884357Z"
    },

The issue I am having is if I use the below code, I cannot get the interest_category "interest_name" and only have the IDs displayed in a GET request:

class InterestSerializer(serializers.ModelSerializer):
    interest_name = serializers.CharField()
    class Meta:
        model = Interests
        fields = ('id', 'interest_name')


class ProjectsSerializer(serializers.ModelSerializer):
    interest_category = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True
    )
    class Meta:
        model = Project
        fields = [
            'project_title',
            'project_description',
            'interest_category',
            'created_by',
            'created_at',
            'updated_at',
        ]

    def create(self, validated_data):
        project_category = validated_data.pop("interest_category", None)
        project_create = Project.objects.create(**validated_data)
        if project_category:
            project_create.interest_category.set(project_category)

        return project_create

I have tried using this to GET the data and I can, however when I use this code, I cannot write and set the interest_category, it will just be blank:

class InterestSerializer(serializers.ModelSerializer):
    interest_name = serializers.CharField()
    class Meta:
        model = Interests
        fields = ('id', 'interest_name')


class ProjectsSerializer(serializers.ModelSerializer):
    interest_category = InterestSerializer(
        many=True, read_only=True
    )
    class Meta:
        model = Project
        fields = [
            'project_title',
            'project_description',
            'interest_category',
            'created_by',
            'created_at',
            'updated_at',
        ]

    def create(self, validated_data):
        project_category = validated_data.pop("interest_category", None)
        project_create = Project.objects.create(**validated_data)
        if project_category:
            project_create.interest_category.set(project_category)

        return project_create

If I use one or the other, I cannot POST the interest_category or I cannot GET the interest_category. How can I make it so I can get the data that I need to GET and POST the request with the same serializer. Any and all help is greatly appreciated!

CodePudding user response:

You can simply override the to_representation() method or inherit InterestSerializer in ProjectsSerializer.

CodePudding user response:

The change that I made is on ProjectsSerializers and Project's views

# The Base of ProjectsSerializers
class BaseProjectsSerializer(serializers.ModelSerializer):
    interest_category = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True
    )
    class Meta:
        model = Project
        fields = [
            'project_title',
            'project_description',
            'interest_category',
            'created_by',
            'created_at',
            'updated_at',
        ]

    def create(self, validated_data):
        project_category = validated_data.pop("interest_category", None)
        project_create = Project.objects.create(**validated_data)
        if project_category:
            project_create.interest_category.set(project_category)

        return project_create

class WriteProjectsSerializer(BaseProjectsSerializer):  # <<<< -------- HERE
    interest_category = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True
    )


class ReadProjectsSerializer(BaseProjectsSerializer):   # <<<< -------- HERE
    interest_category = serializers.SerializerMethodField(read_only=True)
    def get_interest_category(self, instance):
        interest_category = instance.interest_category.all()
        serializer = InterestSerializer(instance=interest_category, many=True)
        return serializer.data

# In your View, add a dict of serializer_classes and set a default serializer
class ProjectViewSet(viewsets.ModelViewSet):
    """Project Viewset"""
    queryset = Project.objects.all()
    default_serializer_class = ReadProjectsSerializer # < --------- HERE
    serializer_classes = {  # < ---------------------------------- HERE
        'create': WriteProjectsSerializer,
        'update': WriteProjectsSerializer,
        'partial_update': WriteProjectsSerializer,
    }

CodePudding user response:

You can try using the StringRelatedField instead of PrimaryKeyRelatedField for your interest_category field in the ProjectsSerializer serializer class:

class ProjectsSerializer(serializers.ModelSerializer):
    interest_category = serializers.StringRelatedField(
        many=True, read_only=True) # new

    # the other lines of code ...

This can get you something like:

{
        "project_title": "Dogs",
        "project_description": "and cats",
        "interest_category": [          
                '4: Test',
                '7: Business'
        ],
        "created_by": 1,
        "created_at": "2022-09-17T04:31:40.884357Z",
        "updated_at": "2022-09-17T04:31:40.884357Z"
    },

You can read more here.

  • Related