Как получить все данные, связанные с serializers.PrimaryKeyRelatedField

Я пытаюсь получить все данные, связанные с этим interest_category сериализатором. Вот что я получаю в настоящее время:

{
        "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"
    },

Что я пытаюсь получить:

{
        "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"
    },

Проблема, с которой я сталкиваюсь, заключается в том, что если я использую следующий код, я не могу получить interest_category "имя_интереса", а только идентификаторы, отображаемые в GET-запросе:

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

Я пробовал использовать это для получения данных и могу, однако когда я использую этот код, я не могу записать и установить interest_category, он будет просто пустым:

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

Если я использую один или другой, я не могу POST interest_category или GET interest_category. Как я могу сделать так, чтобы я мог получить данные, которые мне нужны для GET и POST запроса с одним и тем же сериализатором. Любая помощь будет высоко оценена!

Вы можете просто переопределить метод to_representation() или наследовать InterestSerializer в ProjectsSerializer.

Изменения, которые я сделал, касаются ProjectsSerializers и представлений Project

# 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,
    }

Вы можете попробовать использовать StringRelatedField вместо PrimaryKeyRelatedField для вашего interest_category поля в ProjectsSerializer классе сериализатора:

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

    # the other lines of code ...

В результате вы можете получить что-то вроде:

{
        "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"
    },

Вы можете прочитать больше здесь.

Это можно решить с помощью контекстных данных и опций read_only.

views.py

...

ProjectsSerializer(data=request.data, context={'request': request}

serializers.py


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

class ProjectsSerializer(serializers.ModelSerializer):
    interest_category = InterestSerializer(read_only=True, many=True)

    class Meta:
        model = Project
        fields = [
            'project_title',
            'project_description',
            'interest_category',
            'created_by',
            'created_at',
            'updated_at',
            'interest_category',
        ]

    def create(self, validated_data):
        interest_category = self.context['request'].data.get("interest_category", None)
        project = Project.objects.create(**validated_data)
        if interest_category:
            interests = Interests.objects.filter(id__in=interest_category)
            project_create.interest_category.set(interests)

        return project
Вернуться на верх