Simple Pagination in Django
Pagination refers to organizing returned data in multiple pages, rather than displaying everything on one page. Therefore we need a way of moving from page one, to two, to three e.t.c. This article focuses on how to achieve that using Django.
I will be using this example app on github to explain how the whole process works.
Here is our views.py
file
from django.core.paginator import Paginator
from django.shortcuts import render
from uploads.models import Document
def home(request):
documents = Document.objects.all()
paginator = Paginator(documents, 2) # Show 2 documents per page.
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'uploads/home.html', { 'page_obj' : page_obj })
Explanation
The first line is : documents = Document.objects.all()
and it simply gets all documents in the database and the result of this operation is assigned to the documents
variable.
The socond line is : paginator = Paginator(documents, 2)
. Here we are using the Paginator
class to help us split the results of Documents into pages and each page has only two items.
In the third line we have page_number = request.GET.get('page')
.
- I will start with
request.GET
, this containGET
variables and they usuually appear in the address bar , e.ghttp://127.0.0.1:8000/?page=2
. - The
.get()
is a python method that is normally used to return the value of items with a specific key from a dictionary. If nothing is foundNone
is returned.
so this line page_number = request.GET.get('page')
simply means we are getting the value of a GET
variable that has a name of 'page' and then we assign that to page_number variable.
In the fourth line we have : page_obj = paginator.get_page(page_number)
. This line returns a Page object and If the page isn’t a number, it returns the first page.
Now that we are done with views.py
file , here is how our template looks like
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</span>
</div>
Lets divide the above code into three parts, the first part is
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
Here we are checking if the page object has previous page, if so then add links to the first page and previous page.
This line ?page=1
means we are passing data to the server using the GET method, we are passing the value of 1 to the page parameter.
The next part is
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
The above line shows the current page number against total number of pages.
The last part is
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
This line checks if the page object has next page, if so show links for the next page and the last page, And thats all.
A sample image of how pagination looks like, take a look at the bottom part, we have page 1 of 2 next and last.
Resources
Keep Learning
- What to do when Django's static files are not working
- Chains, Groups and Chords in Celery
- What is __init__() in Python