LearnWagtail.com has a new look! A new course is coming, too! 🥳

Tutorial Wagtail Version: 2.x

How to Paginate Your Wagtail Pages

Pagination is the ability to click through "pages". You most commonly see this on a Blog Listing Page, where you have "page 1 of 4" for example. In this lesson we're going to use Django Paginator right out of the box to add pagination to our Wagtail Blog Listing Page. No 3rd party packages, no craziness, and minimal maintenance. Just beautiful Wagtail and Django working together in 11 lines of code in our Wagtail Page Pagination.

Pagination is the ability to click through "pages". You most commonly see this on a Blog Listing Page, where you have "page 1 of 4" for example.

In this lesson we're going to Django Paginator right out of the box to add pagination to our Wagtail Blog Listing Page. No 3rd party packages, no craziness, minimal maintenance. Below is the the code we used in this video, but if you're looking to learn more about the code (like the exceptions that were used), the video covers all of that.

``` """blog/models.py""" from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from wagtail.core.models import Page class BlogListingPage(Page): """Listing page lists all the Blog Detail Pages.""" template = "blog/blog_listing_page.html" def get_context(self, request, *args, **kwargs): """Adding custom stuff to our context.""" context = super().get_context(request, *args, **kwargs) # Get all posts all_posts = BlogDetailPage.objects.live().public().order_by('-first_published_at') # Paginate all posts by 2 per page paginator = Paginator(all_posts, 2) # Try to get the ?page=x value page = request.GET.get("page") try: # If the page exists and the ?page=x is an int posts = paginator.page(page) except PageNotAnInteger: # If the ?page=x is not an int; show the first page posts = paginator.page(1) except EmptyPage: # If the ?page=x is out of range (too high most likely) # Then return the last page posts = paginator.page(paginator.num_pages) # "posts" will have child pages; you'll need to use .specific in the template # in order to access child properties, such as youtube_video_id and subtitle context["posts"] = posts return context ```
``` {% extends "base.html" %} {# templates/blog/blog_listing_page.html #} {% block content %} {% comment %} {% for post in posts %} {{ post.url }} {% endfor %} {% endcomment %} {# Only show pagination if there is more than one page to click through #} {% if posts.paginator.num_pages > 1 %} <div class="container"> <div class="row"> <div class="col-lg-12"> <div class="pagination"> {% if posts.has_previous %} <li class="page-item"> <a href="?page={{ posts.previous_page_number }}" class="page-link"> <span>&laquo;</span> </a> </li> {% endif %} {% for page_num in posts.paginator.page_range %} <li class="page-item {% if page_num == posts.number %} active{% endif %}"> <a href="?page={{ page_num }}" class="page-link"> {{ page_num }} </a> </li> {% endfor %} {% if posts.has_next %} <li class="page-item"> <a href="?page={{ posts.next_page_number }}" class="page-link"> <span>&raquo;</span> </a> </li> {% endif %} </div> </div> </div> </div> {% endif %} {% endblock content %} ```

Related tutorials

Get notified about new Wagtail content.