Как получить все данные, связанные с 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