Well actually there are a bunch of answers floating around and in django snippets.
I came across this post:
http://www.tummy.com/articles/django-pagination/
Which had the end result i wanted. I just needed to modify it so it would work with Generic Class Based Views, or at least when the same context variables were available.
I'm sure this can be improved, but as it is, I think this is pretty reusable.
- first off create a new app. e.g. my_pagination
- make sure this app is added to INSTALLED_APPS in your settings
- in this app folder make two folders: templatetags and templates
- in the templatetags folder make a file called paginator.py
- in the templates folder make a subfolder called (in this case my_pagination) and add a file called _paginator.html. (putting an underscore in front of filenames is my own convention for included template files)
code for paginator.py
# Based on: http://www.djangosnippets.org/snippets/73/
#
# Modified by Sean Reifschneider to be smarter about surrounding page
# link context. For usage documentation see:
#
# http://www.tummy.com/Community/Articles/django-pagination/
# modified again by me to include target_url and work with django 1.7
from django import template
from django.core.paginator import InvalidPage
register = template.Library()
def paginator(context, adjacent_pages=2, target_url=None):
"""
To be used in conjunction with the object_list generic view.
Adds pagination context variables for use in displaying first, adjacent and
last page links in addition to those created by the object_list generic
view.
"""
startPage = max(context['page_obj'].number - adjacent_pages, 1)
if startPage <= 3: startPage = 1
endPage = context['page_obj'].number + adjacent_pages + 1
if endPage >= context['paginator'].num_pages - 1: endPage = context['paginator'].num_pages + 1
page_numbers = [n for n in range(startPage, endPage) \
if n > 0 and n <= context['paginator'].num_pages]
page_obj = context['page_obj']
paginator = context['paginator']
try:
previous = context['page_obj'].previous_page_number()
except InvalidPage:
previous = None
try:
next = context['page_obj'].next_page_number()
except InvalidPage:
next = None
return {
'page_obj': page_obj,
'paginator': paginator,
'page': context['page_obj'].number,
'page_numbers': page_numbers,
'next': next,
'previous': previous,
'has_next': context['page_obj'].has_next(),
'has_previous': context['page_obj'].has_previous(),
'show_first': 1 not in page_numbers,
# show last if the last page number is not in "page_numbers"
'show_last': context['paginator'].num_pages not in page_numbers,
'target_url' : target_url
}
register.inclusion_tag('my_pagination/_paginator.html', takes_context=True)(paginator)
the code for _paginator.html can be whatever you want as long as you understand the logic (which is pretty straightforward)
I'm using foundation 5 and fontawesome so my _paginator.html looks like
<ul class="pagination">
{% if has_previous %}
<li class="arrow"><a href="{{ target_url }}?page={{ previous }}" target="_parent"><i class="fa fa-angle-double-left fa-lg fa-fw"></i></a></li>
{% else %}
<li class="arrow unavailable"><i class="fa fa-angle-double-left fa-lg fa-fw"></i></li>
{% endif %}
{% if show_first %}
<li><a href="{{ target_url }}?page=1" target="_parent">1</a></li>
<li>...</li>
{% endif %}
{% for linkpage in page_numbers %}
{% if linkpage == page %}
<li class="current">{{ page }}</li>
{% else %}
<li><a href="{{ target_url }}?page={{ linkpage }}" target="_parent">{{ linkpage }}</a></li>
{% endif %}
{% endfor %}
{% if show_last %}
<li>...</li>
<li><a href="{{ target_url }}?page={{ paginator.num_pages }}" target="_parent">{{ paginator.num_pages }}</a></li>
{% endif %}
{% if has_next %}
<li class="arrow"><a href="{{ target_url }}?page={{ next }}" target="_parent"><i class="fa fa-angle-double-right fa-lg fa-fw"></i></a></li>
{% else %}
<li class="arrow unavailable"><i class="fa fa-angle-double-right fa-lg fa-fw"></i></li>
{% endif %}
</ul>
How to use:
in your template file make sure you do:
{% load paginator %}
to load the custom template tag
then where you want the pages to show up you simply do:
{% paginator 3 %}
Notes
1. target_url is simply because of some wierd requirement i had around iframes. You can simply leave this param blank.
2. I took out many of the params from the original because they didn't seem relevant.