Как получить DRF-api в OpenAPI с помощью drf-yasg?

Я создаю простой API, используя Django Rest Framework. Этот API ничего не хранит, но функционирует как прокси для другого API, чтобы запросить, есть ли в магазине молоко. Поэтому я сделал простой сериализатор и представление:

class HasMilkSerializer(serializers.Serializer):
    store = serializers.CharField(min_length=6, max_length=6)
    passage_at = serializers.DateTimeField()

class HasMilkView(CsrfExemptMixin, APIView):
    http_method_names = ['post']
    authentication_classes = [BasicAuthWithKeys]
    serializer_classes = [HasMilkSerializer]

    def post(self, request):
        store = request.data['store']
        visit_at = parser.parse(request.data['visit_at'])
        return Response({'store': store, 'has_milk': has_milk(store, visit_at)})

Это работает отлично, теперь я хочу задокументировать это в спецификациях OpenAPI с помощью drf-yasg. Я установил его, и swagger показывает некоторую информацию, но не показывает никаких спецификаций параметров или ответов (см. скриншот ниже).

Что мне нужно сделать, чтобы swagger правильно документировал мою конечную точку? Нужно ли мне дополнительно определить ее в swagger или изменить конечную точку, чтобы swagger мог правильно ее документировать?

enter image description here

APIView не имеет атрибута serializer_classes и swagger не может определить ваш сериализатор автоматически. вы можете использовать другой тип представления, например GenericAPIView или ModelViewSet.

или

если вы хотите использовать APIView, вам следует использовать декоратор @swagger_auto_schema для определения параметров запроса/ответа:

    @swagger_auto_schema(request_body=HasMilkSerializer)
    def post(self, request):
        store = request.data['store']
        visit_at = parser.parse(request.data['visit_at'])
        return Response({'store': store, 'has_milk': has_milk(store, visit_at)})

Сначала несколько моментов:

  • В APIView (или других классах, которые наследуются от него), атрибутом для определения используемого класса сериализатора является serializer_class, а не serializer_classes.
  • Но поскольку вы не используете класс сериализатора здесь, вам действительно не нужно определять его, насколько я вижу.

Что касается вопроса, поскольку вы используете класс APIView, drf-yasg не может вывести тело запроса и ответа, используя модель queryset. Таким образом, вы должны вручную добавить ответ и тело запроса, используя декоратор swagger_auto_schema. Вы можете сделать примерно следующее:

from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema


class HasMilkView(CsrfExemptMixin, APIView):
    http_method_names = ['post']
    authentication_classes = [BasicAuthWithKeys]
    serializer_classes = [HasMilkSerializer]
    
    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['store', 'visit_at'],
            properties={
                'store': openapi.Schema(type=openapi.TYPE_STRING,
                                        max_length=6),
                'visit_at': openapi.Schema(type=openapi.TYPE_STRING, 
                                           format=FORMAT_DATE)
            }
        ),
        responses={
            200: openapi.Schema(
                type=openapi.TYPE_OBJECT,
                properties={
                    'store': openapi.Schema(type=openapi.TYPE_STRING,
                                        max_length=255),
                    'has_milk': openapi.Schema(type=openapi.TYPE_BOOLEAN)
                }
            )
        }
    )
    def post(self, request):
        store = request.data['store']
        visit_at = parser.parse(request.data['visit_at'])
        return Response({'store': store, 'has_milk': has_milk(store, visit_at)})
Вернуться на верх