Django Class Based Views Pagination with Bootstrap 4

Pagination is an essential part of platforms where one needs to list many items. Instead of displaying all the times, say 50,000 records, pagination allows the user to browse through the entire collection in steps, only seeing a part of the entire collection.

In this article, we take a look at how to get pagination working in Django via Class Based Views. Thus, if you use ListView, for example, using pagination can give us results like this:

The key take away point from the above snippet is the part, paginate_by. The paginate_by attribute is available with the MultipleObjectMixin, (docs)which is a class ListView generic list class inherits from.

At the fundamental level, here’s what the paginate_by field on the ListView class is doing:

Take the returned Queryset of the model, Package

Break them into separate pages, with each page holding a number of, in the case above, 3 items.

Provide handles for switching back and forth between the different pages generated holding the items.

Therefore, if the returned Queryset of the model, Package is made of 50 items, and the paginate_by value is 10, then we will have 5 pages, each holding 10 items.

Enabling the paginate_by attribute on our ListView class gives us certain options and callbacks for free.

Our Template

In our template, let’s play around with our page_objwhich is thrown into the template should pagination be enabled.

Remember: The page_obj will be available in our template if the page is ‘paginable’. As in, if you have a total of 5 items in the returned Queryset, yet you’ve stated a paginate_by value of 100, there’s nothing to paginate, thus the page_objwon’t be there in the template to make use of.

In fact, a boolean, is_paginatedis trued if the returned list is worthy of paginating. We make use of that boolean next.

The code snippet from above is from Bootstrap 4. It has only be altered to reflect the Django template parts, and gives us this visual look:

Django Pagination Bootstrap 4 Look

We make use of the:

is_paginated bool to first check whether we have pagination available. We don’t want a pagination related UI showing without any functionality.

page_obj comes with various methods that make our job easier, such as

has_next andhas_previous

previous_page_number and next_page_number

The above is fairly straightforward as to what they do. However, one feature of our pagination is the fact that we have the number of pages listed, and numbered. We use the .page_range method available from the paginator class to achieve this.