user5500750
user5500750

Reputation:

Django Rest Framework add page number attribute using the PageNumberPagination class

I am building an API using Django and Django rest framework and I am trying to add the page number on the json results. And I am trying to add the page number in the returned results for example, I am currently getting this;

{
  "links": {
    "next": null,
    "previous": null
  },
  "count": 1,
  "results": [
    {
      "url": "http://127.0.0.1:8000/api/brands/1/?format=json",
      "name": "microsoft",
      "description": "Nothing",
      "top_brand": true,
      "guid": "microsoft"
    }
  ]
}

But I am trying to get something like this;

{
  "count": 1,
  "results": [
    {
      "url": "http://127.0.0.1:8000/api/brands/1/?format=json",
      "name": "microsoft",
      "description": "Nothing",
      "top_brand": true,
      "guid": "microsoft"
    },
    ...
  ],
  "page_number": 1,
  "from": 1,
  "to": 10,
  "last_page": 4
}

The most important attribute is the page_number but I am not so sure how to get that from the parent class using self... I see no direct way besides using a function. Here is my code;

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000

    def get_paginated_response(self, data):
        return Response({
            'links': {
                'next': self.get_next_link(),
                'previous': self.get_previous_link()
            },
            'count': self.page.paginator.count,
            'results': data,
            'page_number': self.page.paginator...,
        })

Upvotes: 5

Views: 7029

Answers (5)

Micheal J. Roberts
Micheal J. Roberts

Reputation: 4180

I believe something like this to get the to and from might be more applicable:

class MyCustomPagination(pagination.PageNumberPagination):

    def get_from(self):
        return int((self.page.paginator.per_page * self.page.number) - self.page.paginator.per_page + 1)

    def get_to(self):
        return self.get_from() + int(len(self.page.object_list)) - 1

    def get_paginated_response(self, data):

        return Response({
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'count': self.page.paginator.count,
            'total_pages': self.page.paginator.num_pages,
            'page_number': self.page.number,
            'per_page': self.page.paginator.per_page,
            'from': self.get_from(),
            'to': self.get_to(),
            'results': data
        })

Upvotes: 2

K.A
K.A

Reputation: 1659

to disply the currnet page number in your response basically you can do that on your views.py file by create a custom 'pagination_class ', as the following.

i have model calls 'Comment' , note : this is just example , and change it based on your requirements :

## view all comments with Custom paganation ##
class MyCustomPagination(PageNumberPagination):
    page_size = 1
    page_size_query_param = 'page_size'
    def get_paginated_response(self, data):
        return Response({
            'count': self.page.paginator.count,
            'page_number': self.page.number,
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'results': data,
        })




class C_ApiCommentListView(ListAPIView):
    queryset = Comment.objects.all()
    serializer_class = App1CommentSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    pagination_class = MyCustomPagination
    filter_backends = (SearchFilter, OrderingFilter)
    search_fields = ('COM_comment', 'COM_title', 'COM_user__username')

i hope this helpful for you.

Upvotes: -1

jTiKey
jTiKey

Reputation: 743

Since this was answered, there's a new component that takes a :number-of-pages property.

https://bootstrap-vue.org/docs/components/pagination-nav

Upvotes: 0

user8060120
user8060120

Reputation:

if i understand you correct you can use self.page.number

    return Response({
        'links': {
            'next': self.get_next_link(),
            'previous': self.get_previous_link()
        },
        'count': self.page.paginator.count,
        'results': data,
        'page_number': self.page.number,
        #              ^^^^^^^^^^^^^^^^
    })

Upvotes: 4

Robert
Robert

Reputation: 3483

You can use your custom pagination in viewset and changed on custom view

pagination.py

class CustomPageNumber(pagination.PageNumberPagination):
    page_size = 2

    def get_paginated_response(self, data):
        return Response(OrderedDict([
             ('lastPage', self.page.paginator.count),
             ('countItemsOnPage', self.page_size),
             ('current', self.page.number),
             ('next', self.get_next_link()),
             ('previous', self.get_previous_link()),
             ('results', data)
         ]))

In your view

class TestViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Test.objects.all().order_by('-created_at')
    serializer_class = TestSerializer

    @list_route(methods=['get'], url_path='get-records/(?P<pk>[^/]+)')
    def get_record(self, request, pk):
        self.pagination_class = CustomPageNumber
        queryset = self.filter_queryset(self.queryset.filter(course=pk))
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data) 

and you need configure in your settings.py

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPageNumber',
    'PAGE_SIZE': 100
}

If you want know more refer the docs custom-pagination-class

Upvotes: 13

Related Questions