Как настроить схему response api с помощью drf-spectacular для Django Rest Framework
У меня возникла проблема настройки схемы API.
Вот мой случай: Мне нужно возвращать список экземпляров в моем сериализаторе с его полями, но также должно быть одно общее поле агрегации, которое накапливает эти экземпляры модели в список.
Вот пример структуры json:
{
"comments_amount": 2,
"comments": [
{
"id": 0,
"card_id": 0,
"user_id": 0,
"text": "Comment",
"created_at": "2024-02-24T09:07:43.946Z",
"updated_at": "2024-02-24T09:07:43.946Z"
},
{
"id": 1,
"card_id": 0,
"user_id": 0,
"text": "Comment",
"created_at": "2024-03-24T09:07:43.946Z",
"updated_at": "2024-03-24T09:07:43.946Z"
}
]
}
Вот мой код для сериализатора:
class CommentResponseSerializer(serializers.ModelSerializer):
parent_id = serializers.IntegerField(help_text=_("ID of parent comment"), min_value=0, required=False)
card_id = serializers.IntegerField(help_text=_("Product's card ID"), min_value=0)
user_id = serializers.IntegerField(help_text=_("ID of user who created this comment"), required=True)
class Meta:
model = Comment
exclude = ["user", "parent", "card"]
А вот для просмотра:
@extend_schema(tags=["Product Cards"], summary="API для комментариев карточек продуктов")
class CommentView(APIView):
@extend_schema(
description="API для просмотра комментариев. Доступно всем пользователям.",
parameters=[
OpenApiParameter(
name="card_id", description="ID карточки продукта", required=True, type=int, location="path"
)
],
request=CommentInputSerializer,
responses=CommentResponseSerializer,
)
def get(self, request, *args, **kwargs):
card_id = kwargs["card_id"]
comments = Comment.objects.filter(card_id=card_id)
serializer = CommentResponseSerializer(comments, many=True)
data = {
"comments_amount": comments.count(),
"comments": serializer.data
}
return Response(data, status=status.HTTP_200_OK)
Здесь, как вы можете видеть, я создаю dict
с полем comments_amount
и comments
для самих комментариев с помощью CommentResponseSerializer
.
Как же я могу представить не только поля CommentReponseSerializer
, но и поле comments_amount
с помощью drf-spectacular.
Буду очень благодарен, если кто-нибудь поможет. Я много искал, но не нашел подходящего решения.
После публикации этого вопроса я пришел к довольно простому и очевидному решению. Итак, я создал новый сериализатор:
class CommentResponseWithAmountSerializer(serializers.Serializer):
comments_amount = serializers.IntegerField(help_text=_("Amount of comments"))
comments = CommentResponseSerializer(many=True, help_text=_("List of comments"))
class Meta:
fields = "__all__"
И обновленный метод представления get
:
@extend_schema(
description="API для просмотра комментариев. Доступно всем пользователям.",
parameters=[
OpenApiParameter(
name="card_id", description="ID карточки продукта", required=True, type=int, location="path"
)
],
request=CommentInputSerializer,
responses=CommentResponseWithAmountSerializer,
)
def get(self, request, *args, **kwargs):
card_id = kwargs["card_id"]
comments = Comment.objects.filter(card_id=card_id)
serializer = CommentResponseWithAmountSerializer(
{
"comments_amount": comments.count(),
"comments": CommentResponseSerializer(comments, many=True).data
}
)
return Response(serializer.data, status=status.HTTP_200_OK)