-
-
Notifications
You must be signed in to change notification settings - Fork 13
Pagination Quick Reference
Brian Pepple edited this page Oct 16, 2025
·
1 revision
{% load pagination_tags %}
{# Your list content here #}
{# Standard pagination #}
{% include "comicsdb/partials/pagination.html" %}{% include "comicsdb/partials/pagination.html" %}Shows: [Previous] 1 ... 4 5 [6] 7 8 ... 20 [Next]
Preserves all query params while updating specific ones:
{# Update page, keep all filters #}
<a href="?{% url_replace page=2 %}">Page 2</a>
{# Update multiple params #}
<a href="?{% url_replace page=1 sort='title' %}">Reset & Sort</a>
{# Use variables #}
<a href="?{% url_replace page=page_obj.next_page_number %}">Next</a>Your view must provide these context variables:
context = {
'page_obj': page_obj, # Current page object
'paginator': paginator, # Paginator object
'is_paginated': page_obj.has_other_pages(), # Boolean
}from django.core.paginator import Paginator
from django.shortcuts import render
def my_list_view(request):
# Get your queryset
items = MyModel.objects.all()
# Apply filters (optional)
if search := request.GET.get('q'):
items = items.filter(name__icontains=search)
# Paginate
paginator = Paginator(items, 25) # 25 items per page
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
return render(request, 'my_template.html', {
'page_obj': page_obj,
'paginator': paginator,
'is_paginated': page_obj.has_other_pages(),
}){% load pagination_tags %}
<form method="get">
<input name="q" value="{{ request.GET.q }}" placeholder="Search...">
<button type="submit">Search</button>
</form>
{% for item in page_obj %}
{# Display item #}
{% endfor %}
{% include "comicsdb/partials/pagination.html" %}{% load pagination_tags %}
{# Filters #}
<form method="get">
<select name="category">
<option value="">All Categories</option>
{# options #}
</select>
<input name="year" type="number" value="{{ request.GET.year }}">
<button type="submit">Filter</button>
</form>
{# Sorting #}
<div>
Sort by:
<a href="?{% url_replace sort='name' %}">Name</a>
<a href="?{% url_replace sort='date' %}">Date</a>
</div>
{# Results #}
{% for item in page_obj %}
{# Display item #}
{% endfor %}
{# Pagination preserves filters AND sort #}
{% include "comicsdb/partials/pagination.html" %}{% load pagination_tags %}
{# Tab Navigation #}
<div class="tabs">
<a href="?{% url_replace tab='all' page=1 %}">All</a>
<a href="?{% url_replace tab='active' page=1 %}">Active</a>
<a href="?{% url_replace tab='archived' page=1 %}">Archived</a>
</div>
{# Content #}
{% for item in page_obj %}
{# Display item #}
{% endfor %}
{# Pagination preserves tab selection #}
{% include "comicsdb/partials/pagination.html" %}# In your view
paginator = Paginator(items, 50) # 50 items per pageEdit get_pagination_range in pagination_tags.py:
# Show 3 pages on each side (instead of 2)
page_range = range(
max(1, current_page - 3),
min(total_pages + 1, current_page + 4)
){# Small pagination #}
<nav class="pagination is-small is-rounded">
{# Large pagination #}
<nav class="pagination is-large is-rounded">
{# Left-aligned #}
<nav class="pagination is-left">
{# Right-aligned #}
<nav class="pagination is-right">| Problem | Solution |
|---|---|
Invalid block tag: 'url_replace' |
Add {% load pagination_tags %} at top of template |
| Template tag not found | Restart Django server after creating tag file |
| Filters not preserved | Use {% url_replace %} instead of hardcoded URLs |
| Page numbers wrong | Ensure paginator and page_obj in context |
'request' not in context |
Ensure view passes request to template |
- Django Pagination Docs: https://docs.djangoproject.com/en/stable/topics/pagination/
- Bulma Pagination: https://bulma.io/documentation/components/pagination/
- Template Tags: https://docs.djangoproject.com/en/stable/howto/custom-template-tags/