0

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 ]

1 Answers1

1

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,
            [...]
        },
    ]
}
ThomasGth
  • 826
  • 7
  • 18
  • On the first request, I'd like to only query for the first 10 users (using something like LIMIT and OFFSET), then provide that result along with the total count so the pagination method can provide the proper next, previous, and count properties. Then on the second request, I'd like to use the request information to update the LIMIT and OFFSET and return the next 10. – MdHassan413 Sep 14 '22 at 13:03
  • @MdHassan413 I added an example, but that's exactly what my solution provides. If you really needs limit / offset pagination, [check this](https://www.django-rest-framework.org/api-guide/pagination/#limitoffsetpagination), but from my understanding, you don't really need it for your use-case. Also, you can override `page_size_query_param` if you ever want the page_size to be customizable. – ThomasGth Sep 14 '22 at 13:52
  • Ok, I got your point, and I have a question dose [LimitOffsetPagination](https://www.django-rest-framework.org/api-guide/pagination/#limitoffsetpagination) query all data from `get_queryset ` and then do limit and offset on it or work like directly query from `get_queryset `? – MdHassan413 Sep 15 '22 at 06:00
  • 1
    No, django querysets are lazy, which means it only retrieves the entries needed. Pagination use django paginator, check [this answer](https://stackoverflow.com/a/10549382/6106166) if you want more details on how it works. – ThomasGth Sep 15 '22 at 08:50