11👍
Quite a few nice articles about implementing what you are asking for in django.
Lots of pluggable packages to customize if you don’t want to roll your own.
http://www.tummy.com/Community/Articles/django-pagination/
https://github.com/dcramer/django-paging
Very well document snippet that wraps the built in paginator:
http://blog.elsdoerfer.name/2008/03/06/yet-another-paginator-digg-style/
7👍
I just implemented this using the “Digg-like Paginator” from Django Snippets.
This is definitely what you are looking for.
Just dump that code into a Python module like digg_paginator.py
and import it like so…
from django.core.paginator import InvalidPage, EmptyPage #, Paginator
from digg_paginator import DiggPaginator as Paginator
Then in my templates I had to switch from…
{% for page_num in page.paginator.page_range %}
to
{% for page_num in page.page_range %}
That’s it! The DiggPaginator
has the exact same interface as Django’s built in one plus some features so you can just drop it into place and then adjust it with some customizations if you feel the need.
2👍
I recently had to do the exact same thing for my site Wantbox.com and found a very simple and effective solution.
I add this snippet in my app’s “templatetags” directory in a file called “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/
from django import template
register = template.Library()
def paginator(context, adjacent_pages=2):
"""
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'] - adjacent_pages, 1)
if startPage <= 3: startPage = 1
endPage = context['page'] + adjacent_pages + 1
if endPage >= context['pages'] - 1: endPage = context['pages'] + 1
page_numbers = [n for n in range(startPage, endPage) \
if n > 0 and n <= context['pages']]
page_obj = context['page_obj']
paginator = context['paginator']
return {
'page_obj': page_obj,
'paginator': paginator,
'hits': context['hits'],
'results_per_page': context['results_per_page'],
'page': context['page'],
'pages': context['pages'],
'page_numbers': page_numbers,
'next': context['next'],
'previous': context['previous'],
'has_next': context['has_next'],
'has_previous': context['has_previous'],
'show_first': 1 not in page_numbers,
'show_last': context['pages'] not in page_numbers,
}
register.inclusion_tag('paginator.html', takes_context=True)(paginator)
Then I add this to the page where I want the pagination:
<div>{% if is_paginated %}{% load paginator %}{% paginator 3 %}{% endif %}</div>
Changing the “3” to “2” or “4” modifies how the pagination truncates. You can see an example on my site here (top right of the page).
0👍
If you are using ListView, here is your paginator function:
def paginator(context, adjacent_pages=2):
"""
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']
return {
'page_obj': page_obj,
'paginator': paginator,
'page': context['page_obj'].number,
'pages': context['paginator'].num_pages,
'page_numbers': page_numbers,
'next': context['page_obj'].next_page_number,
'previous': context['page_obj'].previous_page_number,
'has_next': context['page_obj'].has_next,
'has_previous': context['page_obj'].has_previous,
'show_first': 1 not in page_numbers,
'show_last': context['paginator'].num_pages not in page_numbers,
}
My Template
<nav>
<ul class="pagination">
<li{% if not page_obj.has_previous %} class="disabled"{% endif %}>
<a {% if page_obj.has_previous %} href="?{{ path }}page={{ page_obj.previous_page_number }}"{% endif %}><i
class="fa fa-angle-left"></i></a>
</li>
{% if show_first %}
<li><a href="?{{ path }}page=1">1</a></li>
<li class="disabled"><a>…</a></li>
{% endif %}
{% for linkpage in page_numbers %}
{% ifequal linkpage page %}
<li class="active"><a>{{ page }}</a></li>
{% else %}
<li><a href="?{{ path }}page={{ linkpage }}">{{ linkpage }}</a></li>
{% endifequal %}
{% endfor %}
{% if show_last %}
<li class="disabled"><a>…</a></li>
<li><a href="?{{ path }}page=last">{{ pages }}</a></li>
{% endif %}
<li{% if not page_obj.has_next %} class="disabled"{% endif %}>
<a {% if page_obj.has_next %} href="?{{ path }}page={{ page_obj.next_page_number }}"{% endif %}><i
class="fa fa-angle-right"></i></a>
</li>
</ul>
</nav>