How to add Pagination in Django Project?
Last Updated :
22 May, 2025
Pagination system is one of the most common features in blogs, search engine , list of result etc. Seeing the popularity of pagination system django developers have build a Paginator class so that web developers do not have to think of the logic to make paginators.
What is the Paginator Class?
The Paginator class is located in django/core/paginator.py. It helps divide a list of objects into pages, making it easy to display a subset of objects per page.
Importing Paginator
To use the paginator, import it along with some exceptions from Django:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Basic Syntax
p = paginator(list_of_objects, no_of_objects_per_page)
- list_of_objects: This can be a list, tuple, queryset, or any sliceable object with a count() or __len__() method.
- objects_per_page: Number of objects to display on each page.
Optional Arguments:
- orphans (int): If the last page has fewer than or equal to this number of objects, they will be added to the previous page. Default is 0.
- allow_empty_first_page (bool): Whether the first page is allowed to be empty. Default is True..
Steps to Implement Pagination in Django
Prerequisites:
Create or Use a Django Project and App
If you don’t have a Django project or app yet, create them:
django-admin startproject myproject
cd myproject
python manage.py startapp blog
Define Your Model (Post)
In your app’s models.py, define the Post model if not already done:
Python
from django.shortcuts import render
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def index(request):
posts = Post.objects.all() # fetching all post objects from database
p = Paginator(posts, 5) # creating a paginator object
# getting the desired page number from url
page_number = request.GET.get('page')
try:
page_obj = p.get_page(page_number) # returns the desired page object
except PageNotAnInteger:
# if page_number is not an integer then assign the first page
page_obj = p.page(1)
except EmptyPage:
# if page is empty then return last page
page_obj = p.page(p.num_pages)
context = {'page_obj': page_obj}
# sending the page object to index.html
return render(request, 'index.html', context)
Create and Apply Migrations
Run the following commands to create the database table:
python manage.py makemigrations
python manage.py migrate
Add Some Sample Data
You can add posts via the Django admin or shell:
python manage.py shell
Then inside the shell:
from blog.models import Post
Post.objects.create(title="Post 1", author="Author 1", content="Content 1")
Post.objects.create(title="Post 2", author="Author 2", content="Content 2")
# ... create at least 8 posts as in the example
Exit the shell with exit().
In your app’s views.py, add the pagination code:
Python
from django.shortcuts import render
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def index(request):
posts = Post.objects.all()
paginator = Paginator(posts, 5) # Show 5 posts per page
page_number = request.GET.get('page')
try:
page_obj = paginator.get_page(page_number)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
context = {'page_obj': page_obj}
return render(request, 'index.html', context)
Create a folder named templates inside your app folder (blog/templates/) and inside it create index.html.
Add this template content:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django Paginator example</title>
</head>
<body>
<div class="container">
{% for post in page_obj.object_list %}
{# note that the list of posts are in the page_obj.object_list not page_obj #}
<h1>{{post.title}}</h1>
<small>{{post.author}}</small>
<p>{{post.content}}</p>
<hr/>
{% endfor %}
</div>
<center>
{%if page_obj.has_previous %} {# whether the previous page exists #}
<a href="?page={{page_obj.previous_page_number}}"><</a> {# link to the prev page #}
{% endif %}
<span>{{page_obj.number}}</span> {# the current page number #}
{%if page_obj.has_next %} {# whether the next page exists #}
<a href="?page={{page_obj.next_page_number}}">></a> {# link to the next page #}
{% endif %}
</center>
</body>
</html>
- Use page_obj.object_list to iterate through the posts on the current page.
- Use page_obj.has_previous and page_obj.has_next to conditionally show navigation arrows.
- Clicking the arrows sends a GET request with the page parameter to navigate pages.
In your app, create (or edit) urls.py (blog/urls.py):
Python
from django.urls import path
from .views import index
urlpatterns = [
path('', index, name='index'),
]
Then include your app’s URLs in the project’s main urls.py (myproject/urls.py):
Python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')), # Make sure your app is included here
]
Run the Server
Start the Django development server:
python manage.py runserver
Output:
In the image we have send the value of the page number with a GET request ( denoted with rectangle). You can see the pagination in the bottom of the image ( marked with rectangle ).
Here is another image of the last page:
