Open In App

How to add Pagination in Django Project?

Last Updated : 22 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

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().

Create the View with Pagination

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.

Configure URLs

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:


Next Article

Similar Reads