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>«</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>»</span>
</a>
</li>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
{% endblock content %}