PAGINATION IN DJANGO In 15 Minutes

PAGINATION IN DJANGO In 15 Minutes

Spreading out your content over several pages as opposed to presenting it all at once would greatly enhance the user experience of your Django web project. Pagination is the term for this method.

Instead of dumping all the data on the user at once, you can specify how many records should be presented per page and then give back the data that matches the page that the user requested.

Django provides a Paginator class to manage paginated data.

Django Paginator class

In Django, all methods of pagination use the Paginator class which is imported from django.core.paginator.

The paginator class takes 4 parameters.

class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True, error_messages=None)
  • object_list - (Required). A list, tuple, QuerySet or other sliceable object with a count() or __len__() method. source documentation
  • per_page - (Required) maximum number of items to include on a page.
  • orphans - (Optional: by default 0): Use this when you don’t want to have a last page with very few items. If the last page would normally have a number of items less than or equal to orphans, then those items will be added to the previous page (which becomes the last page) instead of leaving the items on a page by themselves. For example, with 23 items, per_page=10, and orphans=3, there will be two pages; the first page with 10 items and the second (and last) page with 13 items. orphans defaults to zero, which means pages are never combined and the last page may have one item.
  • allow_empty_first_page - Optional. Whether or not the first page is allowed to be empty. If False and object_list is empty, then an EmptyPage error will be raised.
  • error_messages - Optional - The error_messages argument lets you override the default messages that the paginator will raise. Pass in a dictionary with keys matching the error messages you want to override. Available error message keys are: invalid_page, min_page, and no_results.
>>> paginator = Paginator(
...     [1, 2, 3],
...     2,
...     error_messages={"no_results": "Page does not exist"},
... )
>>> paginator.page(5)
Traceback (most recent call last):
  ...
EmptyPage: Page does not exist

Django Paginator Example

Django models.py

We have a Book model and a total of 13 books in our database.

#models.py

from django.db import models

class Book(models.Model):
    name = models.CharField('Book name', max_length=100)
    author = models.CharField('Author', max_length=100)
    published = models.DateField('Published')

    def __str__(self):
        return self.name

Let’s do it in the shell. We have a total of 13 books in our database.

from demo.models import Book

books = Book.objects.all()
books.values_list('name')

# we have total 13 items
<QuerySet [('Django Design Patterns and Best Practices',), ('Django Unleashed',), ('Beginning Django E-Commerce',), ('Django for APIs',), ('Django for Beginners',), ('Django for Professionals',), ('Two Scoops of Django',), ('Django 2 by Example',), ('Lightweight Django 1st Edition',), ('Practical Django 2 and Channels 2',), ('Test-Driven Development with Python',), ('Learn Web Development with Python',), ('Build Your First Website with Python and Django 1st Edition',)]>

Paginator object attributes

  • count - total number of objects, across all pages
  • num_pages - total number of pages.
  • page_range - a 1-based range iterator of page numbers, e.g. yielding [1, 2, 3, 4].
from django.core.paginator import Paginator

p = Paginator(books, per_page=5)
p.count  
# Output: 13

p.num_pages
# Output: 3
# it means 5 items on page 1, 5 items on page 2, 3 on page 3

p.page_range
# Ouput: range(1, 4)

Page class methods

  • has_next() - returns True if there’s a next page.
  • has_previous() - returns True if there’s a previous page
  • has_other_pages() - returns True if there’s a next or previous page.
  • next_page_number() - returns the next page number. Raises InvalidPage if next page doesn’t exist
  • previous_page_number() - returns the previous page number. Raises InvalidPage if previous page doesn’t exist
  • start_index() - for example, when paginating a list of 5 objects with 2 objects per page, the second page’s start_index() would return 3.
  • end_index() - for example, when paginating a list of 5 objects with 2 objects per page, the second page’s end_index() would return 4
  • source: documentation
from django.core.paginator import Paginator

p = Paginator(books, per_page=5)    # book has 13 items
page1 = p.page(1)
page1 # Output: <Page 1 of 3>

page1.object_list  # It will return 5 items per page as we set per_page=5
Output: <QuerySet [<BookModel: Django Design Patterns and Best Practices>, <BookModel: Django Unleashed>, <BookModel: Beginning Django E-Commerce>, <BookModel: Django for APIs>, <BookModel: Django for Beginners>]>

page1.has_next() # True

page1.has_previous()  # False

page1.has_other_pages()  # True

page1.next_page_number()  # 2

# It will return Exception EmptyPage: because we dont have previous page num
page1.previous_page_number()

page1.start_index() # 1

page1.end_index() # 5

p.page(0)
# Exception: EmptyPage: That page number is less than 1

p.page(4)
# Exception: EmptyPage: The page contains no results

I hope It’s clear to you. If you want more detail then visit the documentation . Now let’s move toward the main part.

Django admin.py

Register your model in admin.py

# admin.py

from django.contrib import admin
from .models import Book

admin.site.register(Book)

Django Pagination with Function-based views

django views.py

# views.py

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Book
from django.shortcuts import render

def book_list(request):
    books = Book.objects.all()
    page = request.GET.get('page', 1)
    paginator = Paginator(books, 5)  #  paginate_by 5
    try:
        books = paginator.page(page)
    except PageNotAnInteger:
        books = paginator.page(1)
    except EmptyPage:
        books = paginator.page(paginator.num_pages)
    return render(request, "books.html", {"books": books})

django urls.py

# urls.py

from django.urls import path
from .views import book_list

urlpatterns = [
    path('all-books', book_list, name='all_books')
]

Template (books.html)

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <title>Books</title>
  </head>
  <body>
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
          <h1 class="display-4">Django Books</h1>
          <!-- It will show the total books count -->
          <p class="lead">List of Django Books - {{ books.paginator.count }}</p>
        </div>
      </div>
    <div class="container">
        <table class="table">
            <thead class="thead-dark">
              <tr>
                <th scope="col">#</th>
                <th scope="col">Name</th>
                <th scope="col">Author</th>
                <th scope="col">Date</th>
              </tr>
            </thead>
            <tbody>
                {% for book in books %}
                    <tr>
                        <td>{{ forloop.counter }} </td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.author }}</td>
                        <td>{{ book.published }}</td>
                    </tr>
                {% endfor %}
            </tbody>
          </table>
          <!-- pagination starts -->
          <nav aria-label="...">
            <ul class="pagination flex-wrap justify-content-center">
              <li class="page-item disabled">
                {% if books.has_previous %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page={{ books.previous_page_number }}"></a>
                  </li>
                {% endif %}
                {% if books.number > 3 %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page=1">1</a>
                  </li>
                {% endif %}
                {% if books.number > 4 %}
                    <li class="page-item">
                    <span class="page-link">....</span>
                    </li>
                {% endif %}
              </li>
              {% for i in books.paginator.page_range %}
                {% if books.number == i %}
                  <li class="page-item active">
                    <span class="page-link">
                      {{ i }}
                      <span class="sr-only"></span>
                    </span>
                  </li>
                  {% elif i > books.number|add:'-3' and i < books.number|add:'3' %}
                    <li class="page-item">
                      <a class="page-link" href="{{ request.path }}?page={{ i }}">{{ i }}</a>
                    </li>
                {% endif %}
              {% endfor %}
              {% if books.has_next %}
                {% if books.number < books.paginator.num_pages|add:'-3' %}
                    <li class="page-item">
                        <span class="page-link">....</span>
                    </li>
                    <li class="page-item">
                        <a class="page-link" href="?page={{ books.paginator.num_pages }}">{{ books.paginator.num_pages }}</a>
                    </li>
                {% elif books.number < books.paginator.num_pages|add:'-2' %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ books.paginator.num_pages }}">{{ books.paginator.num_pages }}</a>
                    </li>
                {% endif %}  
                <li class="page-item">
                  <a class="page-link" href="?page={{ books.next_page_number }}"></a>
                </li>
              {% endif %}
            </ul>
          </nav>
          <!-- pagination end -->
    </div>
    <!-- Optional JavaScript; choose one of the two! -->
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
  </body>
</html>

Django Pagination with Class-based views

views.py
# views.py

from django.views.generic import ListView
from .models import Book

class BookListView(ListView):
    model = Book
    template_name = 'books_class_based.html'
    context_object_name = 'books'
    paginate_by = 5
    queryset = BookModel.objects.all()

Template (books_class_based.html)
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <title>Books</title>
  </head>

  <body>
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
          <h1 class="display-4">Django Books</h1>
          <!-- It will show the total books count -->
          <p class="lead">List of Django Books - {{ page_obj.paginator.count }}</p>
        </div>
      </div>
    <div class="container">
        <table class="table">
            <thead class="thead-dark">
              <tr>
                <th scope="col">#</th>
                <th scope="col">Name</th>
                <th scope="col">Author</th>
                <th scope="col">Date</th>
              </tr>
            </thead>
            <tbody>
                {% for book in books %}
                    <tr>
                        <td>{{ forloop.counter }} </td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.author }}</td>
                        <td>{{ book.published }}</td>
                    </tr>
                {% endfor %}
            </tbody>
          </table>
          <!-- pagination starts -->
          <nav aria-label="...">
            <ul class="pagination flex-wrap justify-content-center">
              <li class="page-item disabled">
                {% if page_obj.has_previous %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page={{ page_obj.previous_page_number }}"></a>
                  </li>
                {% endif %}
                {% if page_obj.number > 3 %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page=1">1</a>
                  </li>
                {% endif %}
                {% if page_obj.number > 4 %}
                    <li class="page-item">
                    <span class="page-link">....</span>
                    </li>
                {% endif %}
              </li>
              {% for i in page_obj.paginator.page_range %}
                {% if page_obj.number == i %}
                  <li class="page-item active">
                    <span class="page-link">
                      {{ i }}
                      <span class="sr-only"></span>
                    </span>
                  </li>
                  {% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
                    <li class="page-item">
                      <a class="page-link" href="{{ request.path }}?page={{ i }}">{{ i }}</a>
                    </li>
                {% endif %}
              {% endfor %}
              {% if page_obj.has_next %}
                {% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
                    <li class="page-item">
                        <span class="page-link">....</span>
                    </li>
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">{{ page_obj.paginator.num_pages }}</a>
                    </li>
                {% elif page_obj.number < page_obj.paginator.num_pages|add:'-2' %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">{{ page_obj.paginator.num_pages }}</a>
                    </li>
                {% endif %}  
                <li class="page-item">
                  <a class="page-link" href="?page={{ page_obj.next_page_number }}"></a>
                </li>
              {% endif %}
            </ul>
          </nav>
          <!-- pagination end -->
    </div>
    <!-- Optional JavaScript; choose one of the two! -->
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
  </body>
</html>

Dynamic pagination with filter (Function-based views)

views.py
# views.py

def book_list(request):
    author = request.GET.get('author')
    paginate_by = request.GET.get('paginate_by')
    if author:
        books = BookModel.objects.filter(author=author)
    else:
        books = BookModel.objects.all()

    page = request.GET.get('page', 1)

    if paginate_by is None:
        paginator = Paginator(books, 5)  # paginate_by 5
    else:
        paginator = Paginator(books, paginate_by)

    try:
        books = paginator.page(page)
    except PageNotAnInteger:
        books = paginator.page(1)
    except EmptyPage:
        books = paginator.page(paginator.num_pages)

     # if you do not add this code then if you are on page 2
     # and you select paginate by 7 then ?page=2 will be removed
     # from URL and you left with only ?paginate_by=2
     # so if you want something like this ?paginate_by=5&page=2 and 
     # add the following code
    _request_copy_1 = request.GET.copy()
    _request_copy_2 = request.GET.copy()
    page_parameter = _request_copy_1.pop('page', True) and _request_copy_1.urlencode()
    paginate_parameter = _request_copy_2.pop('paginate_by', True) and _request_copy_2.urlencode()
    return render(request, "books.html", {
        "books": books, "page_parameter": page_parameter,
        "paginate_parameter": paginate_parameter
        })
Template
<!-- books.html -->
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <title>Books</title>
  </head>
  <body>
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
          <h1 class="display-4">Django Books</h1>
          <!-- It will show the total books count -->
          <p class="lead">List of Django Books - {{ books.paginator.count }}</p>
          <div class="dropdown">
            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Paginate By {{ request.GET.paginate_by }}
            </button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
              <a class="dropdown-item" href="?paginate_by=5&{{paginate_parameter}}">5</a>
              <a class="dropdown-item" href="?paginate_by=7&{{paginate_parameter}}">7</a>
              <a class="dropdown-item" href="?paginate_by=10&{{paginate_parameter}}">10</a>
            </div>
          </div>
          <form class="form-inline mt-2" method="get">
              <div class="form-group mb-2">
                <input name="author" type="text" class="form-control" placeholder="Search author">
              </div>
              <button type="submit" class="btn btn-secondary mb-2">Search</button>
        </form>
        </div>
    </div>
    <div class="container">
        <table class="table">
            <thead class="thead-dark">
              <tr>
                <th scope="col">#</th>
                <th scope="col">Name</th>
                <th scope="col">Author</th>
                <th scope="col">Date</th>
              </tr>
            </thead>
            <tbody>
                {% for book in books %}
                    <tr>
                        <td>{{ forloop.counter }} </td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.author }}</td>
                        <td>{{ book.published }}</td>
                    </tr>
                {% endfor %}
            </tbody>
          </table>
          <!-- pagination starts -->
          <nav aria-label="...">
            <ul class="pagination flex-wrap justify-content-center">
              <li class="page-item disabled">
                {% if books.has_previous %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page={{ books.previous_page_number }}&{{page_parameter}}"></a>
                  </li>
                {% endif %}
                {% if books.number > 3 %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page=1&{{page_parameter}}">1</a>
                  </li>
                {% endif %}
                {% if books.number > 4 %}
                    <li class="page-item">
                    <span class="page-link">....</span>
                    </li>
                {% endif %}
              </li>
              {% for i in books.paginator.page_range %}
                {% if books.number == i %}
                  <li class="page-item active">
                    <span class="page-link">
                      {{ i }}
                      <span class="sr-only"></span>
                    </span>
                  </li>
                  {% elif i > books.number|add:'-3' and i < books.number|add:'3' %}
                    <li class="page-item">
                      <a class="page-link" href="{{ request.path }}?page={{ i }}&{{page_parameter}}">{{ i }}</a>
                    </li>
                {% endif %}
              {% endfor %}
              {% if books.has_next %}
                {% if books.number < books.paginator.num_pages|add:'-3' %}
                    <li class="page-item">
                        <span class="page-link">....</span>
                    </li>
                    <li class="page-item">
                        <a class="page-link" href="?page={{ books.paginator.num_pages }}&{{page_parameter}}">{{ books.paginator.num_pages }}</a>
                    </li>
                {% elif books.number < books.paginator.num_pages|add:'-2' %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ books.paginator.num_pages }}&{{page_parameter}}">{{ books.paginator.num_pages }}</a>
                    </li>
                {% endif %}  
                <li class="page-item">
                  <a class="page-link" href="?page={{ books.next_page_number }}&{{page_parameter}}"></a>
                </li>
              {% endif %}
            </ul>
          </nav>
          <!-- pagination end -->
    </div>
    <!-- Optional JavaScript; choose one of the two! -->
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
  </body>
</html>

Dynamic pagination with filter (Class-based views)

views.py
class BookListView(ListView):
    model = BookModel
    template_name = 'books_class_based.html'
    context_object_name = 'books'
    paginate_by = 5

    def get_queryset(self):
        author = self.request.GET.get('author')
        if author:
            books = BookModel.objects.filter(author=author)
        else:
            books = BookModel.objects.all()
        return books

    def get_paginate_by(self, queryset):
        if 'paginate_by' in self.request.GET:
            return self.request.GET['paginate_by']
        else:
            return self.paginate_by

    def get_context_data(self, *args, **kwargs):
       # if you do not add this code then if you are on page 2
       # and you select paginate by 7 then ?page=2 will be removed
       # from URL and you left with only ?paginate_by=2
       # so if you want something like this ?paginate_by=5&page=2 and 
       # add the following code

        _request_copy_1 = self.request.GET.copy()
        _request_copy_2 = self.request.GET.copy()
        page_parameter = _request_copy_1.pop('page', True) and _request_copy_1.urlencode()
        paginate_parameter = _request_copy_2.pop('paginate_by', True) and _request_copy_2.urlencode()
        context = super().get_context_data(*args, **kwargs)
        context['page_parameter'] = page_parameter
        context['paginate_parameter'] = paginate_parameter
        return context

Template
{% comment %} books_class_based.html {% endcomment %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <title>Books</title>
  </head>
  <body>
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
          <h1 class="display-4">Django Books</h1>
          <!-- It will show the total books count -->
          <p class="lead">List of Django Books - {{ page_obj.paginator.count }}</p>
          <div class="dropdown">
            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Paginate By {{ request.GET.paginate_by }}
            </button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
              <a class="dropdown-item" href="?paginate_by=2&{{paginate_parameter}}">2</a>
              <a class="dropdown-item" href="?paginate_by=5&{{paginate_parameter}}">5</a>
              <a class="dropdown-item" href="?paginate_by=7&{{paginate_parameter}}">7</a>
              <a class="dropdown-item" href="?paginate_by=10&{{paginate_parameter}}">10</a>
            </div>
          </div>
          <form class="form-inline mt-2" method="get">
            <div class="form-group mb-2">
              <input name="author" type="text" class="form-control" placeholder="Search author">
            </div>
            <button type="submit" class="btn btn-secondary mb-2">Search</button>
        </form>
        </div>
      </div>
    <div class="container">
        <table class="table">
            <thead class="thead-dark">
              <tr>
                <th scope="col">#</th>
                <th scope="col">Name</th>
                <th scope="col">Author</th>
                <th scope="col">Date</th>
              </tr>
            </thead>
            <tbody>
                {% for book in books %}
                    <tr>
                        <td>{{ forloop.counter }} </td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.author }}</td>
                        <td>{{ book.published }}</td>
                    </tr>
                {% endfor %}
            </tbody>
          </table>
          <!-- pagination starts -->
          <nav aria-label="...">
            <ul class="pagination flex-wrap justify-content-center">
              <li class="page-item disabled">
                {% if page_obj.has_previous %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page={{ page_obj.previous_page_number }}&{{page_parameter}}"></a>
                  </li>
                {% endif %}
                {% if page_obj.number > 3 %}
                  <li class="page-item">
                    <a class="page-link" href="{{ request.path }}?page=1&{{page_parameter}}">1</a>
                  </li>
                {% endif %}
                {% if page_obj.number > 4 %}
                    <li class="page-item">
                    <span class="page-link">....</span>
                    </li>
                {% endif %}
              </li>
              {% for i in page_obj.paginator.page_range %}
                {% if page_obj.number == i %}
                  <li class="page-item active">
                    <span class="page-link">
                      {{ i }}
                      <span class="sr-only"></span>
                    </span>
                  </li>
                  {% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
                    <li class="page-item">
                      <a class="page-link" href="{{ request.path }}?page={{ i }}&{{page_parameter}}">{{ i }}</a>
                    </li>
                {% endif %}
              {% endfor %}
              {% if page_obj.has_next %}
                {% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
                    <li class="page-item">
                        <span class="page-link">....</span>
                    </li>
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}&{{page_parameter}}">{{ page_obj.paginator.num_pages }}</a>
                    </li>
                {% elif page_obj.number < page_obj.paginator.num_pages|add:'-2' %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}&{{page_parameter}}">{{ page_obj.paginator.num_pages }}</a>
                    </li>
                {% endif %}  
                <li class="page-item">
                  <a class="page-link" href="?page={{ page_obj.next_page_number }}&{{page_parameter}}"></a>
                </li>
              {% endif %}
            </ul>
          </nav>
          <!-- pagination end -->
    </div>
    <!-- Optional JavaScript; choose one of the two! -->
    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
  </body>
</html>

SUBSCRIBE FOR NEW ARTICLES

@
comments powered by Disqus