WDTUTORIALS
menu
Django - The Easy Way Django - The Easy Way
Samuli Natri 2018.02.11
Entrepreneur. Software developer since the 90's. He attended Helsinki University Of Technology (Computer Science) and Helsinki University (Social Sciences).

Django - Pagination Examples

Tutorial on how to create and style a pager.

Quickstart

 View

from django.shortcuts import render
from blog.models import Post
from django.core.paginator import Paginator # < Import the Paginator class

def home(request):
    
    posts = Post.objects.all()
    paginator = Paginator(posts, 3) # < 3 is the number of items on each page
    page = request.GET.get('page') # < Get the page number
    
    posts = paginator.get_page(page) # < New in 2.0!
    
    return render(request, 'base/home.html', {'posts': posts})

Markup Example 1

<div class="pagination">
 
  {% if posts.has_previous %}
  <a href="?page=1">First</a>
  <a href="?page={{ posts.previous_page_number }}">Previous</a>
  {% endif %}

  <span>{{ posts.number }}</span>
  <span">of</span>
  <span>{{ posts.paginator.num_pages }}</span>

  {% if posts.has_next %}
  <a href="?page={{ posts.next_page_number }}">Next</a>
  <a href="?page={{ posts.paginator.num_pages }}">Last</a>
  {% endif %}
</div>

Markup Example 2

<div class="pagination">
 
  {% if posts.has_previous %}
  <a href="?page=1">First</a>
  <a href="?page={{ posts.previous_page_number }}">Previous</a>
  {% endif %}

  {% for num in posts.paginator.page_range %}

    {% if posts.number == num %}
    <span>{{ num }}</span>
    {% elif num > posts.number|add:'-3' and num < posts.number|add:'3' %}
    <a href="?page={{ num }}">{{ num }}</a>
    {% endif %}

  {% endfor %}

  {% if posts.has_next %}
  <a href="?page={{ posts.next_page_number }}">Next</a>
  <a href="?page={{ posts.paginator.num_pages }}">Last</a>
  {% endif %}
 
</div>

Source for the page range limit: https://stackoverflow.com/a/45717542

Details

More details on how to build the paginated posts object:

View

Import the Paginator class:

from django.core.paginator import Paginator

Call the Paginator class object and give it at least two arguments: the items you want to paginate and the number of items you want to see on each page:

paginator = Paginator(posts, 3)

This will instantiate the paginator object that we can use to access the page items.

Get the pagination page number from the request object:

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

When you request a page, an HttpRequest object is passed to the view. This contains data about the request like the HTTP GET parameters.

In this case we will be sending the page number in the url like this mysite.com/?page=2.

Use the get_page method with the page number to fetch Page object that we will use to access items in any given page:

posts = paginator.get_page(page)

Django 1.11

Same as the 2.0 version but we handle invalid and out of range page numbers manually:

View

from django.shortcuts import render
from blog.models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # < Import these

def home(request):
    
    posts = Post.objects.all()
    paginator = Paginator(posts, 3)
    page = request.GET.get('page')

    # Handle out of range and invalid page numbers:
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    
    return render(request, 'base/home.html', {'posts': posts})

Blue Theme

Blue theme that shows couple of wing pages in addition to the current page. Use the view from the 2.0 Quickstart tab to build the Posts object.

Result

Template

<div class="pagination">

  {% if posts.has_previous %}
    <a class="pagination-action" href="?page=1">
     <i class="fa fa-angle-double-left" aria-hidden="true"></i>
    </a>
    <a class="pagination-action" href="?page={{ posts.previous_page_number }}">
      <i class="fa fa-angle-left" aria-hidden="true"></i>
    </a>
  {% endif %}
 
  {% for num in posts.paginator.page_range %}
    
    {% if posts.number == num %}
    <span class="pagination-number pagination-current">{{ num }}</span>
    {% elif num > posts.number|add:'-3' and num < posts.number|add:'3' %}
    <a class="pagination-number" href="?page={{ num }}">{{ num }}</a>
    {% endif %}
 
  {% endfor %}
    
  {% if posts.has_next %}
    <a class="pagination-action" href="?page={{ posts.next_page_number }}">
      <i class="fa fa-angle-right" aria-hidden="true"></i>
    </a>
    <a class="pagination-action" href="?page={{ posts.paginator.num_pages }}">
      <i class="fa fa-angle-double-right" aria-hidden="true"></i>
    </a>
  {% endif %}
    
</div>

Fontawesome

Load fontawesome in the head section:

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

CSS

.pagination {
    text-align: center;
    margin-top: 1em;
}

.pagination-number {
    padding: 0.5em 0.8em;
    border-radius: 2px;
    color: #fff;
    background-color: #6D85C7;
}

.pagination-number:hover, .pagination-current {
    background-color: #3354AA;      
}

.pagination-action {
    margin: 0 0.1em;
    display: inline-block;
    padding: 0.5em 0.5em;
    color: #B9B9B9;
    font-size: 1.3em;
}

.pagination-action:hover, .pagination-previous, .pagination-next {
    color: #3354AA;  
}

Green Theme

Green theme that shows current page and total number of pages. Use the view from the Quickstart to build the Posts object.

Result

Template

<div class="pagination">

  {% if posts.has_previous %}
    <a class="pagination-action" href="?page=1">
     <i class="fa fa-angle-double-left" aria-hidden="true"></i>
    </a>
    <a class="pagination-action" href="?page={{ posts.previous_page_number }}">
      <i class="fa fa-angle-left" aria-hidden="true"></i>
    </a>
  {% endif %}

  <span class="pagination-current">{{ posts.number }}</span>
  <span class="pagination-of">of</span>
  <span class="pagination-total">{{ posts.paginator.num_pages }}</span>
    
  {% if posts.has_next %}
    <a class="pagination-action" href="?page={{ posts.next_page_number }}">
      <i class="fa fa-angle-right" aria-hidden="true"></i>
    </a>
    <a class="pagination-action" href="?page={{ posts.paginator.num_pages }}">
      <i class="fa fa-angle-double-right" aria-hidden="true"></i>
    </a>
  {% endif %}
    
</div>

Fontawesome

Load fontawesome in the head section:

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

CSS

pagination {
    text-align: center;
    margin-top: 1em;
}

.pagination-current, .pagination-total {
    padding: 0.5em 0.8em;
    border-radius: 2px;
    color: #fff;
    background-color: #30BF61;    
}

.pagination-total {
    background-color: #B9B9B9;
}

.pagination-action {
    margin: 0 0.1em;
    display: inline-block;
    padding: 0.5em 0.5em;
    color: #B9B9B9;
    font-size: 1.3em;
}

.pagination-of {
    color: #B9B9B9;
    padding: 0 1em;
}


.pagination-action:hover {
    color: #3354AA;  
}

 

I hope some of this content has been useful to you!
Consider supporting my work:

One Time Payment
Subscription