diff --git a/.gitignore b/.gitignore index d7c2b72..7abee5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc dist *.egg-info +build diff --git a/pagination/paginator.py b/pagination/paginator.py index f67aa23..23faf27 100644 --- a/pagination/paginator.py +++ b/pagination/paginator.py @@ -1,5 +1,25 @@ from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage + +class ConcretePaginator(Paginator): + """ + Fix on the Django paginator that now uses an xrange, which isn't + compatible with the slicing that goes on in the template tags here. + """ + + def _get_page_range(self): + """ + Returns a 1-based range of pages for iterating through within + a template for loop. + """ + r = super(ConcretePaginator, self)._get_page_range() + if not isinstance(r, list): + r = list(r) + return r + page_range = property(_get_page_range) + + + class InfinitePaginator(Paginator): """ Paginator designed for cases when it's not important to know how many total diff --git a/pagination/templatetags/pagination_tags.py b/pagination/templatetags/pagination_tags.py index 1d544f0..7d570fd 100644 --- a/pagination/templatetags/pagination_tags.py +++ b/pagination/templatetags/pagination_tags.py @@ -4,11 +4,14 @@ from sets import Set as set from django import template -from django.template import TOKEN_BLOCK +from django.template.base import TOKEN_BLOCK from django.http import Http404 -from django.core.paginator import Paginator, InvalidPage +from django.core.paginator import InvalidPage from django.conf import settings +from pagination.paginator import ConcretePaginator + + register = template.Library() DEFAULT_PAGINATION = getattr(settings, 'PAGINATION_DEFAULT_PAGINATION', 20) @@ -21,12 +24,12 @@ def do_autopaginate(parser, token): """ Splits the arguments to the autopaginate tag and formats them correctly. """ - # Check whether there are any other autopaginations are later in this template expr = lambda obj: (obj.token_type == TOKEN_BLOCK and \ len(obj.split_contents()) > 0 and obj.split_contents()[0] == "autopaginate") - multiple_paginations = len(filter(expr, parser.tokens)) > 0 - + + multiple_paginations = any((expr(tok) for tok in parser.tokens)) + split = token.split_contents() as_index = None context_var = None @@ -99,7 +102,7 @@ def render(self, context): paginate_by = self.paginate_by else: paginate_by = self.paginate_by.resolve(context) - paginator = Paginator(value, paginate_by, self.orphans) + paginator = ConcretePaginator(value, paginate_by, self.orphans) try: page_obj = paginator.page(context['request'].page(page_suffix)) except InvalidPage: @@ -221,7 +224,6 @@ def paginate(context, window=DEFAULT_WINDOW, hashtag=''): pages.extend(differenced) to_return = { 'MEDIA_URL': settings.MEDIA_URL, - 'request': context['request'], 'pages': pages, 'records': records, 'page_obj': page_obj, @@ -231,6 +233,7 @@ def paginate(context, window=DEFAULT_WINDOW, hashtag=''): 'page_suffix': page_suffix, } if 'request' in context: + to_return['request'] = context['request'] getvars = context['request'].GET.copy() if 'page%s' % page_suffix in getvars: del getvars['page%s' % page_suffix] @@ -239,7 +242,7 @@ def paginate(context, window=DEFAULT_WINDOW, hashtag=''): else: to_return['getvars'] = '' return to_return - except KeyError, AttributeError: + except (KeyError, AttributeError): return {} register.inclusion_tag('pagination/pagination.html', takes_context=True)( diff --git a/pagination/tests.py b/pagination/tests.py index f1cad49..7ae3b39 100644 --- a/pagination/tests.py +++ b/pagination/tests.py @@ -1,166 +1,176 @@ -""" ->>> from django.core.paginator import Paginator ->>> from pagination.templatetags.pagination_tags import paginate ->>> from django.template import Template, Context - ->>> p = Paginator(range(15), 2) ->>> pg = paginate({'paginator': p, 'page_obj': p.page(1)}) ->>> pg['pages'] -[1, 2, 3, 4, 5, 6, 7, 8] ->>> pg['records']['first'] -1 ->>> pg['records']['last'] -2 - ->>> p = Paginator(range(15), 2) ->>> pg = paginate({'paginator': p, 'page_obj': p.page(8)}) ->>> pg['pages'] -[1, 2, 3, 4, 5, 6, 7, 8] ->>> pg['records']['first'] -15 ->>> pg['records']['last'] -15 - ->>> p = Paginator(range(17), 2) ->>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] -[1, 2, 3, 4, 5, 6, 7, 8, 9] - ->>> p = Paginator(range(19), 2) ->>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] -[1, 2, 3, 4, None, 7, 8, 9, 10] - ->>> p = Paginator(range(21), 2) ->>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] -[1, 2, 3, 4, None, 8, 9, 10, 11] - -# Testing orphans ->>> p = Paginator(range(5), 2, 1) ->>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] -[1, 2] - ->>> p = Paginator(range(21), 2, 1) ->>> pg = paginate({'paginator': p, 'page_obj': p.page(1)}) ->>> pg['pages'] -[1, 2, 3, 4, None, 7, 8, 9, 10] ->>> pg['records']['first'] -1 ->>> pg['records']['last'] -2 - ->>> p = Paginator(range(21), 2, 1) ->>> pg = paginate({'paginator': p, 'page_obj': p.page(10)}) ->>> pg['pages'] -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ->>> pg['records']['first'] -19 ->>> pg['records']['last'] -21 - ->>> p = Paginator(range(21), 2, 1) ->>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] -[1, 2, 3, 4, None, 7, 8, 9, 10] - ->>> t = Template("{% load pagination_tags %}{% autopaginate var 2 %}{% paginate %}") - ->>> from django.http import HttpRequest as DjangoHttpRequest ->>> class HttpRequest(DjangoHttpRequest): -... page = lambda self, suffix: 1 - ->>> t.render(Context({'var': range(21), 'request': HttpRequest()})) -u'\\n\\n