How to Add Pagination in Django Website

Pagination is the most basic and important of any website. Pagination greatly improves the user experience. With pagination, user can escape from scrolling the long list of contents. In this tutorial, we’ll learn how to add pagination to our Django website. And doing this in Django is very easy (I promise!). Ready to start?

Project setup

Let’s setup our django project and a django app:

django-admin startproject django_pagination
cd django_pagination
django-admin startapp app

Change the django_pagination/urls.py file as below:

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls'))
]

Add our app to the list of INSTALLED_APPS in your django_pagination/settings.py:

....
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app'
]
....

We’re done with basic project setup.

Making our app

Make a file called urls.py in your app/ folder and add the lines below to it:

from django.urls import path
from . import views
urlpatterns = [
    path('', views.pagination, name="pagination")
]

Now, let’s make a model to store our data that should get paginated. Make a simple model as below in your app/models.py file:

from django.db import models
class Post(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    def __str__(self):
        return self.title

And now we’ll write our one and only function in our app/views.py. Add the lines below to your app/views.py:

from django.shortcuts import render
from .models import Post
from django.core.paginator import Paginator
def pagination(request):
    post_models = Post.objects.all()
    paginator = Paginator(post_models, 2)
    page_number = request.GET.get('page')
    page_object = paginator.get_page(page_number)
    return render(request, 'index.html', {'page_objects': page_object})

We’re importing a class called Paginator from django.core.paginator. This enables us to use pagination in Django. We’re initializing a paginator object from this Paginator class. And we’re initializing this with the list (Query set to be precise) of objects of our Post model and a number denoting the maximum number of objects to be displayed per page. In our case, we passed a number 2, so a maximum of 2 post objects will get displayed in our page.

Next, we gathered the current page number by request.GET.get('page'). This is inbuilt template variable that is controlled by Pagination class and what it does is that it grabs the current page number. And this page number is used to get the objects corresponding to that page by paginator.get_page(page_number). Finally, page_object contains all the objects that corresponds to that particular page number.

This is a broad overview of what is happening but feel free to explore the Django docs for pagination.

Adding our templates

Finally, we need to setup our templates. Create a folder called templates in your app/ directory. And make a file with name index.html in that folder you created. Add the followind content to it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="Description" content="Enter your description here" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css">
    <title>Pagination</title>
</head>
<body>
    <div class="container mt-5">
        {% for page in page_objects %}
        <div style="border: 1px solid black">
            {{page.title}}
            <br>
            {{page.description}}
        </div>
        {% endfor %}
    </div>
    <div class="text-center container mt-5">
        {% if page_objects.has_previous %}
        <a class="poppins-font p-2" href="?page={{page_objects.previous_page_number}}">
            Previous
        </a>
        {% endif %}
        <a href="" class="poppins-font p-2 active-btn text-dark" style="background-color: #00e1ff;">
            {{page_objects.number}}
        </a>
        {% if page_objects.has_next %}
        <a class="poppins-font p-2" href="?page={{page_objects.next_page_number}}">
            Next
        </a>
        {% endif %}
    </div>
</body>
</html>

I’m using bootstrap for my styling. What we’re basically doing is, firstly we’re displaying the list of page_objects. Secondly, we’re making a couple of conditional statements. To put these simply, we’ll display previous link only when our page_objects has some objects before them (Previous pages). We’ll display the current page number. Finally, we’ll display next only when our page_objects has some more objects to accomodate in the next page(s). That’s it! Please take a look at href of each anchor tag for better understanding.

Running our project

Now, before running our project, we need to execute the following statement:

python manage.py makemigrations
python manage.py migrate 

Then we need to add some data to our Page model. We’ll do this in our admin panel by creating a superuser with the following command:

python manage.py createsuperuser

Now, for our Page model to get displayed in our admin panel we need to register our model, to do this add the following lines to your app/admin.py:

from django.contrib import admin
from .models import Post
admin.site.register(Post)

Run the server with the following command:

python manage.py runserver

Open the admin panel by visiting 127.0.0.1:8000/admin in your favourite browser and login to the admin panel with the credentials you’ve used to create the superuser. There open Posts table and add a few dummy models with title and description.

After adding dummy models, Visit 127.0.0.1:8000. Then you’ll see our output with pagintion.

Get the code a my Github repo: https://github.com/Chandu-4444/django_pagination