from rest_framework.pagination import PageNumberPagination, CursorPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 25
page_size_query_param = 'page_size'
max_page_size = 100
class FeedCursorPagination(CursorPagination):
page_size = 20
ordering = '-created_at' # Must be an indexed field
cursor_query_param = 'cursor'
from rest_framework import viewsets
from .pagination import StandardResultsSetPagination
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
pagination_class = StandardResultsSetPagination
I use PageNumberPagination for simple, bookmark-friendly pagination and CursorPagination when data changes frequently (prevents duplicate/missing items between pages). Creating a custom pagination class lets me control page_size, page_size_query_param, and max_page_size. I return metadata like count and next/previous URLs in the response. For APIs with heavy queries, I cache total counts or estimate them. Cursor pagination is stateless and efficient but doesn't support jumping to arbitrary pages. I choose based on use case.