Search code examples
python-3.xdjangodjango-rest-frameworkdjango-viewsdrf-queryset

custom pagination of limit and page in Django Rest Framework


I wanted to create custom paginations for this get_queryset.

get_queryset = Comments.objects.filter(language_post_id=post_in_lang_id,is_post_comment=True).order_by('-created_on')[offset:offset+limit]

I want to change the offset value whenever the page_no updates. Suppose someone enters page_no=1, so offset must be 0, and when enters 2, so offset should be 10, and so on. Every time page_no updates, it should update the offset value accordingly.

  • like ?page_no=3:
get_queryset = Comments.objects.filter(language_post_id=post_in_lang_id,is_post_comment=True).order_by('-created_on')[offset:offset+limit] # [ 20 : 20 + 10 ]

Solution

  • I guess you want to do that in a ListAPIView. If that's the case, you can do this really simply using PageNumberPagination.
    Just define the page size and the page_query_param you want, and the default paginate_queryset() method will take care of everything for you, you don't have to override it or calculate the offset by yourself.

    # pagination.py
    from rest_framework.pagination import PageNumberPagination
    
    class CustomPagination(PageNumberPagination):
        # Returns 10 elements per page, and the page query param is named "page_no"
        page_size = 10
        page_query_param = 'page_no'
    
    
    # views.py
    from rest_framework.generics import ListAPIView
    from my_app.pagination import CustomPagination
    
    class MyListView(ListAPIView):
        pagination_class = CustomPagination
        serializer_class = CommentSerializer
        
        def get_queryset(self): 
            post_in_lang_id = '1'  # Retrieve your post_in_lang_id here
            return Comments.objects.filter(language_post_id=post_in_lang_id,is_post_comment=True).order_by('-created_on')
    

    You can also set it as the default paginator by defining DEFAULT_PAGINATION_CLASS in your settings file.

    Here is a mock of what you would get as a result for the first page using this method :

    {
        "count": 20,
        "previous": null,
        "next": "http://localhost:8000/api/comments/?page_no=2",
        "results": [  # List of first 10 elements
            {
                "id": 1,
                [...]
            },
            [...]
            {
                "id": 10,
                [...]
            },
        ]
    }