LimitOffsetPagination in Django Rest Framework

Last updated 1 month, 1 week ago | 114 views 75     5

Tags:- Python Django DRF

When building APIs, it's important to manage large datasets efficiently. Django Rest Framework (DRF) provides several pagination strategies — one of the most flexible being LimitOffsetPagination.

This article covers:

  • What LimitOffsetPagination is

  • How it works

  • How to configure and use it

  • Code example

  • Tips and common pitfalls


What is LimitOffsetPagination?

LimitOffsetPagination allows clients to specify:

  • How many items they want (limit)

  • Where to start in the dataset (offset)

This gives the client more control over how they retrieve data compared to PageNumberPagination.

Example URL:

GET /api/posts/?limit=10&offset=20

→ Retrieves 10 posts starting from the 21st record.


⚙️ How it Works

DRF intercepts requests to views using LimitOffsetPagination and applies the requested limit and offset to the queryset. The response includes pagination metadata and the sliced results.

Default Behavior:

Parameter Default
limit DEFAULT_LIMIT (10 if not set)
offset 0 (starts at the beginning)

Setting Up LimitOffsetPagination

Step 1: Set it Globally (Optional)

In settings.py:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,  # used as default limit
}

You can also override the pagination class per-view.


Step 2: Define a Custom Pagination Class (Optional)

# pagination.py
from rest_framework.pagination import LimitOffsetPagination

class CustomLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5
    max_limit = 50

Step 3: Use it in a View

from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from .pagination import CustomLimitOffsetPagination

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    pagination_class = CustomLimitOffsetPagination

✅ Example Response

{
  "count": 125,
  "next": "http://localhost:8000/api/posts/?limit=5&offset=10",
  "previous": "http://localhost:8000/api/posts/?limit=5&offset=0",
  "results": [
    {
      "id": 11,
      "title": "Post 11",
      "content": "..."
    },
    ...
  ]
}

✅ Complete Code Example

models.py

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

serializers.py

from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'content']

pagination.py

from rest_framework.pagination import LimitOffsetPagination

class CustomLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5
    max_limit = 100

views.py

from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from .pagination import CustomLimitOffsetPagination

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    pagination_class = CustomLimitOffsetPagination

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet

router = DefaultRouter()
router.register('posts', PostViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

Tips & Best Practices

Tip Why It Helps
✅ Use max_limit Prevents abuse by large data requests
✅ Combine with caching Avoids reprocessing identical queries
✅ Use count field to show total available records  
✅ Use in infinite scroll UIs Easier to manage than page-based pagination

⚠️ Common Pitfalls

Pitfall Fix
❌ Missing limit parameter returns default only Set PAGE_SIZE or default_limit to control behavior
❌ Exposing entire dataset by setting huge limit Always use max_limit
❌ Using in views without pagination_class Pagination won’t be applied
❌ Relying on offset for frequently-changing data Use CursorPagination for stable pagination in such cases

PageNumberPagination vs LimitOffsetPagination

Feature PageNumberPagination LimitOffsetPagination
Simple ✅ Yes ❌ Slightly more complex
Infinite Scroll Friendly ❌ No ✅ Yes
Control over data size ❌ No ✅ Yes
Ideal for user interfaces with page numbers ✅ Yes ❌ Not ideal

Conclusion

LimitOffsetPagination provides flexibility and fine-grained control to clients when interacting with large datasets. It's ideal for APIs consumed by JavaScript frontends and mobile apps, especially where infinite scrolling or dynamic loading is needed.

If you need a more secure and stable pagination for large, changing datasets, check out CursorPagination next.