drf-yasg
drf-yasg copied to clipboard
Question: pagination on APIView(Post)
Hi,
Is it possible to do pagination on a post in an APIView? I don't seem to understand how that could be done. I've got the following:
class LargeResultPagination(PageNumberPagination):
"""
Paginator for all apis
"""
page_size = 100000
max_page_size = 100000
page_size_query_param = 'page_size'
class Data(APIView):
"""
Demo of my view
"""
pagination_class = LargeResultPagination
@swagger_auto_schema(
operation_description='...,
request_body=BodySerializer,
responses={200: ReturnSerializer(
many=True
)},
pagination_class=LargeResultPagination,
paginator_inspectors=[PaginatorInspector]
)
def post(self, request, version, format=None):
...
But the swagger page doesn't show any pagination in the responses model. What am I understanding wrong?
I also need answer for this problem, in the documents mentioned that paginator_inspectors
is the only way to add pagination to the response example, but this case it doesn't seem to work with APIView(even on GET request).
I have the same problem - in my case i have custom serializer in list-action in my ModelViewSet, that is different from the serializer_class
. I use swagger_auto_schema
same way
class SomeViewSet(viewsets.ModelViewSet):
serializer_class = SomeSerializer
...
@swagger_auto_schema(responses={200: SomeCustomSerializer(many=True)})
def list(self, request):
...
But in generated swagger docs i see just a list of data from SomeCustomSerialaizer, not wrapped in DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination
. I also use the default DEFAULT_PAGINATOR_INSPECTORS
settings.
It seems when i specify responses
, drf-yasg ignores default pagination settings. Also explicit indication on pginator inspectors in swagger_auto_schema
does not help.
I have sort of fix for that situation.
https://github.com/tuenut/drf-yasg/commit/d20c44afd6674cd3e66ea350564e6c08e1f16cc1
But i have not tested that solution and can say what ripple it can produce. You can crea your own subclass of SwaggerAutoSchema
and override that method, and then use that subclass like as
@swagger_auto_schema(
auto_schema=YourOwnSubclassOfSwaggerAutoSchema,
responses={200: SomeCustomSerializer(many=True)}
)
def list(self, request):
...
My solution for this. Only for APIView
. Works with any methods of APIView
: GET, POST, PATCH, PUT, DELETE.
from drf_yasg import openapi
from drf_yasg.utils import guess_response_status
from drf_yasg.inspectors import SwaggerAutoSchema
class CustomSwaggerAutoSchema(SwaggerAutoSchema):
def get_responses(self):
response_serializers = self.get_response_serializers()
response_schemas = self.get_response_schemas(response_serializers)
paginator = self.overrides.get('paginator', None)
if paginator and self.has_list_response():
method = self.method.lower()
default_response_status = str(guess_response_status(method))
if default_response_status in response_schemas:
response_schemas[default_response_status] = openapi.Response(
description=response_schemas[default_response_status].description,
schema=self.get_paginated_response(
response_schemas[default_response_status].schema
)
)
return openapi.Responses(responses=response_schemas)
def get_paginated_response(self, response_schema):
return self.probe_inspectors(self.paginator_inspectors, 'get_paginated_response',
self._get_paginator(), response_schema=response_schema)
def get_pagination_parameters(self):
if not self.should_page():
return []
return self.probe_inspectors(self.paginator_inspectors, 'get_paginator_parameters',
self._get_paginator()) or []
def should_page(self):
return self._get_paginator() and self.has_list_response()
def _get_paginator(self):
return self.overrides.get('paginator') or getattr(self.view, 'paginator', None)
In settings:
SWAGGER_SETTINGS = {
...
'DEFAULT_AUTO_SCHEMA_CLASS': 'website_apps.api.utils.swagger.CustomSwaggerAutoSchema',
}
In view code:
class EntityListView(APIView):
class ListPagination(pagination.CursorPagination):
page_size = 20
@swagger_auto_schema(
operation_description=_('Returns entity list with pagination'),
query_serializer=EntityListQueryFilter(),
responses={
200: openapi.Response(
description=_('Paginated entity list'),
schema=EntityOutputSerializer(many=True)
)
},
paginator=ListPagination()
)
def get(self, request):
serializer = serializers.EntityListQueryFilter(data=request.query_params)
serializer.is_valid(raise_exception=True)
entities = get_entities(**serializer.validated_data)
paginator = self.ListPagination()
entities = paginator.paginate_queryset(entities, request)
serializer = EntityOutputSerializer(entities, many=True)
return paginator.get_paginated_response(serializer.data)