Paginate without errors if a page doesn't exist

This commit is contained in:
Danielle McLean 2024-05-19 15:59:43 +10:00
parent 8d8aa4749b
commit d21d4bda83
Signed by untrusted user: 00dani
GPG key ID: 6854781A0488421C
2 changed files with 29 additions and 32 deletions

View file

@ -1,35 +1,32 @@
from django.core.paginator import Paginator from typing import Callable
from django.core.paginator import Page, Paginator
from django.shortcuts import redirect from django.shortcuts import redirect
from lemoncurry.middleware import ResponseException from lemoncurry.middleware import ResponseException
def paginate(queryset, reverse, page): def paginate(queryset, reverse: Callable[[int], str], page: int | None) -> Page:
class Page: def redirect_to_page(i: int):
def __init__(self, i): raise ResponseException(redirect(reverse(i)))
self.i = i
@property def reversible(p: Page) -> Page:
def url(self): p.reverse = reverse
return reverse(self.i) return p
@property
def current(self):
return self.i == entries.number
# If the first page was requested, redirect to the clean version of the URL
# with no page suffix.
if page == 1:
raise ResponseException(redirect(Page(1).url))
paginator = Paginator(queryset, 10) paginator = Paginator(queryset, 10)
entries = paginator.page(page or 1)
entries.pages = tuple(Page(i) for i in paginator.page_range) # If no page number was specified, return page one.
if page is None:
return reversible(paginator.page(1))
if entries.has_previous(): # If the first page was explicitly requested, or the page number was negative, redirect to page one with no URL suffix.
entries.prev = Page(entries.previous_page_number()) if page <= 1:
if entries.has_next(): redirect_to_page(1)
entries.next = Page(entries.next_page_number())
return entries # If the page requested is larger than the last page, then redirect to the last page.
if page > paginator.num_pages:
redirect_to_page(paginator.num_pages)
# Just return the current page! Hooray!
return reversible(paginator.page(page))

View file

@ -110,29 +110,29 @@
<nav> <nav>
<ul class="pagination"> <ul class="pagination">
{% if entries.prev %} {% if entries.has_previous() %}
<li class="page-item"> <li class="page-item">
<a class="page-link" rel="prev" href="{{ entries.prev.url }}"> <a class="page-link" rel="prev" href="{{ entries.reverse(entries.previous_page_number()) }}">
<i class="fas fa-step-backward" aria-hidden="true"></i> <span class="sr-only">previous page</span> <i class="fas fa-step-backward" aria-hidden="true"></i> <span class="sr-only">previous page</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% for page in entries.pages %} {% for i in entries.paginator.page_range %}
{% if page.current %} {% if i == entries.number %}
<li class="page-item active"> <li class="page-item active">
<span class="page-link">{{ page.i }} <span class="sr-only">(current page)</span></span> <span class="page-link">{{ i }} <span class="sr-only">(current page)</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="{{ page.url }}">{{ page.i }}</a> <a class="page-link" href="{{ entries.reverse(i) }}">{{ i }}</a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if entries.next %} {% if entries.has_next() %}
<li class="page-item"> <li class="page-item">
<a class="page-link" rel="next" href="{{ entries.next.url }}"> <a class="page-link" rel="next" href="{{ entries.reverse(entries.next_page_number()) }}">
<i class="fas fa-step-forward" aria-hidden="true"></i> <span class="sr-only">next page</span> <i class="fas fa-step-forward" aria-hidden="true"></i> <span class="sr-only">next page</span>
</a> </a>
</li> </li>