DEV Community

Pavel Loginov
Pavel Loginov

Posted on

User-Friendly Django Pagination

Pagination is a common practice in web development used to divide large datasets into smaller and more manageable parts displayed on multiple pages.

Let's consider a successful example of pagination in Django using the Paginator class. This type of pagination is user-friendly and usually suitable for most cases.

Pagination UI

This type of pagination allows you to:

  • Move to the next and previous pages using the Prev and Next buttons;
  • Move to the first and last pages from any page;
  • Navigate by skipping one page at a time.

Pagination in Django

You can find detailed information about pagination in Django from the following links:

In summary, pagination in Django is accomplished using the Paginator and Page classes. The Paginator class divides a large dataset into pages, taking a set of objects (list, tuple, or QuerySet) and the page size as parameters. The Page class represents the current page in pagination and contains the page objects and information about neighboring pages.

You can create a paginator manually or automatically using Class-Based Views. The template is passed the page object (page_obj), which contains the objects, page information, and the paginator itself.

Attributes used in the presented pagination:

  • page_obj.has_previous: Checks if there is a previous page.
  • page_obj.has_next: Checks if there is a next page.
  • page_obj.previous_page_number: Returns the number of the previous page.
  • page_obj.next_page_number: Returns the number of the next page.
  • page_obj.number: Returns the number of the current page.
  • page_obj.paginator: Returns an instance of the Paginator class.
  • page_obj.paginator.num_pages: Returns the total number of pages.
  • page_obj.paginator.page_range: Returns the range of pages.

The presented pagination also uses the add template filter, which allows adding values to variables directly in the template.

User-Friendly Pagination

The screenshot shows how the paginator will look on different pages. The paginator always displays the extreme pages and two neighboring pages, if they exist. The Prev and Next buttons are also displayed if the current page is not an extreme page.

Paginator on different pages

The following listing shows the implementation of this pagination. Simply insert this code into your project, and it should work. We will examine this listing in more detail.

{% if page_obj.has_previous %}
  <li><a href="?page={{ page_obj.previous_page_number }}">(Prev)</a></li>

  {% if page_obj.number > 3 %}
      <li><a href="?page=1">(1)</a></li>
    {% if page_obj.number > 4 %}
      <li><a >...</a></li>
    {% endif %}
  {% endif %}
{% endif %}

{% for num in page_obj.paginator.page_range %}
  {% if page_obj.number == num %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% endif %}
{% endfor %}

{% if page_obj.has_next %}
  {% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
    <li><a >...</a></li>
    <li><a 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><a href="?page={{ page_obj.paginator.num_pages }}">
      ({{ page_obj.paginator.num_pages }})
    </a></li>
  {% endif %}

  <li><a href="?page={{ page_obj.next_page_number }}">(Next)</a></li>
{% endif %}

Enter fullscreen mode Exit fullscreen mode

This code snippet is a Django template for creating a pagination control element. Let's go through what each part of this code does:

1. Link to Previous Page:
{% if page_obj.has_previous %}
  <li><a href="?page={{ page_obj.previous_page_number }}">(Prev)</a></li>
Enter fullscreen mode Exit fullscreen mode

If page_obj.has_previous is True, it shows the Prev button to go to the previous page. The variable page_obj.previous_page_number contains the number of the previous page.

2. Links to First Pages and Ellipsis:
{% if page_obj.number > 3 %}
    <li><a href="?page=1">(1)</a></li>
  {% if page_obj.number > 4 %}
    <li><a >...</a></li>
  {% endif %}
{% endif %}
Enter fullscreen mode Exit fullscreen mode

These lines of code handle the display of a link to the first page and an ellipsis (...) if the current page number is greater than 3 (or 4 for the ellipsis).

3. Current Page and Links to Neighboring Pages:
{% for num in page_obj.paginator.page_range %}
  {% if page_obj.number == num %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
      <li><a href="?page={{ num }}">({{ num }})</a></li>
  {% endif %}
{% endfor %}
Enter fullscreen mode Exit fullscreen mode

This loop goes through the page range in the paginator. It checks two conditions:

  • If the page number (num) is the current page (page_obj.number), it creates a link for it. Typically, this is styled differently to indicate the current page.
  • If the page number is within three pages before or after the current page, it also creates links to these pages. This allows the user to navigate to the nearest two pages without viewing the entire range.
4. Ellipsis and Link to Last Page:
{% if page_obj.has_next %}
  {% if page_obj.number < page_obj.paginator.num_pages|add:'-3' %}
    <li><a >...</a></li>
    <li><a 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><a href="?page={{ page_obj.paginator.num_pages }}">
      ({{ page_obj.paginator.num_pages }})
    </a></li>
  {% endif %}
Enter fullscreen mode Exit fullscreen mode

This part is similar to the second section, but for the end of the pagination range. It displays an ellipsis and a link to the last page if the current page is several pages away from the last page.

5. Link to Next Page:
{% if page_obj.has_next %}
...
<li><a href="?page={{ page_obj.next_page_number }}">(Next)</a></li>
{% endif %}
Enter fullscreen mode Exit fullscreen mode

Similar to the first section, but for the button to go to the next page.

Conclusion

We have explored an example of a simple and user-friendly pagination in Django that allows users to navigate through pages and access the desired information easily.

The pagination implementation can be adapted to your needs, and you can make changes to the code to fit your project requirements. Good luck using pagination in your Django applications!

Top comments (0)