So, you have a Generic ListView . which returns a huge query set of objects. This may not seem a problem at first. But as the application grows this will become a huge bottleneck as the users will have to face huge load time. and this thing multiplied by even just 100’s of users will be devasting for the backend to handle.
So, here pagination comes to save the day. By paginating we mean we are going to deliver the data in chunks or as much as the user requests. so we divide the queryset into pages of equal chunks maybe 10 objects or 20. And serve them according to the request from user.
Implementing Pagination can be made pretty much easy by using the generic class-based view called ListVew. If you are not using CBV"s you are missing a lot.
you can get started from the docs here .
Let’s get started.
from django.db import models
class Shirt(models.Model):
name = models.CharField(max_length=255)
As we have a model Shirt for our imaginary T-shirt store. Now as the models are set we need a view to process the data and render the HTML page .
let us create a T-shirt ListView.
from django.views.generic import ListView
from .models import Shirt
class ShirtListView(ListView):
"""
this is our View which renders a list of t-shirts
implementing pagination is pretty straight forward . We just need
to add the pagianate_by attribute and set the value to size we
want to return for each page
"""
model = Shirt
paginate_by= 5
template_name ="app/tshirts.html"
Now the view is set up. Don’t forget to add a URL path to the view in the urls.py file. Now we need to render the objects in the template and also put links to remaining or previous pages. This may seem a little tricky but it isn’t. Django again simplifies it for us, when we use the paginate_by attribute in the view. Django also adds a page_obj to the context. which holds the data like current page, next, previous page, total pages and etc.
We can request a specific page by by adding a page query param to the URL followed the no of the page required .
so /?page=1 will return the first page and /?page=2 will return the second page.
So, with the help of all of this. we can set up simple and robust pagination in few minutes. Let us create tshirts.html template file and see it in action.
<!-- non required part truncated -->
<!-- our pagination lies here -->
<ul class="pagination pagination-info">
<span class="step-links">
<!-- check if there is a previous page or is it is first -->
{% if page_obj.has_previous %}
<li class="page-item" > <a class= "page-link" href="?page=1">« first </a></li>
<li class="page-item" > <a class= "page-link" href="?page={{ page_obj.previous_page_number }}"> prev </a></li>
{% endif %}
<span class="current">
<li class="active page-item"><a href="javascript:void(0);" class="page-link"> {{ page_obj.number }} </a></li>
</span>
<!-- check if there is next page or is it is last -->
{% if page_obj.has_next %}
<li class="page-item"><a href="?page={{ page_obj.next_page_number }}" class="page-link">Next </a></li>
<li class="page-item"><a href="?page={{ page_obj.paginator.num_pages }}" class="page-link">last</a></li>
{% endif %}
</span>
</ul>
<!-- non required part truncated -->