From: Stanislav Panasik <spanasik@gmail.com> Date: Sun, 11 Jul 2010 12:26:16 +0000 (+0600) Subject: Added support for multiple paginations on the same template. (Florian Schlachter ) X-Git-Tag: release-2.0~33^2 X-Git-Url: https://git.mdrn.pl/django-pagination.git/commitdiff_plain/786f413a03df1e4d0485213d8c1d796d15ac114d?page=2 Added support for multiple paginations on the same template. (Florian Schlachter ) --- diff --git a/pagination/middleware.py b/pagination/middleware.py index f8a2a6f..676f909 100644 --- a/pagination/middleware.py +++ b/pagination/middleware.py @@ -1,10 +1,10 @@ -def get_page(self): +def get_page(self, suffix): """ A function which will be monkeypatched onto the request to get the current integer representing the current page. """ try: - return int(self.REQUEST['page']) + return int(self.REQUEST['page%s' % suffix]) except (KeyError, ValueError, TypeError): return 1 @@ -14,4 +14,4 @@ class PaginationMiddleware(object): it exists in either **GET** or **POST** portions of the request. """ def process_request(self, request): - request.__class__.page = property(get_page) \ No newline at end of file + request.__class__.page = get_page \ No newline at end of file diff --git a/pagination/templates/pagination/pagination.html b/pagination/templates/pagination/pagination.html index fe566a8..c2fb72d 100644 --- a/pagination/templates/pagination/pagination.html +++ b/pagination/templates/pagination/pagination.html @@ -2,7 +2,7 @@ {% load i18n %} <div class="pagination"> {% if page_obj.has_previous %} - <a href="?page={{ page_obj.previous_page_number }}{{ getvars }}{{ hashtag }}" class="prev">‹‹ {% trans "previous" %}</a> + <a href="?page{{ page_suffix }}={{ page_obj.previous_page_number }}{{ getvars }}" class="prev">‹‹ {% trans "previous" %}</a> {% else %} <span class="disabled prev">‹‹ {% trans "previous" %}</span> {% endif %} @@ -11,14 +11,14 @@ {% ifequal page page_obj.number %} <span class="current page">{{ page }}</span> {% else %} - <a href="?page={{ page }}{{ getvars }}{{ hashtag }}" class="page">{{ page }}</a> + <a href="?page{{ page_suffix }}={{ page }}{{ getvars }}" class="page">{{ page }}</a> {% endifequal %} {% else %} ... {% endif %} {% endfor %} {% if page_obj.has_next %} - <a href="?page={{ page_obj.next_page_number }}{{ getvars }}{{ hashtag }}" class="next">{% trans "next" %} ››</a> + <a href="?page{{ page_suffix }}={{ page_obj.next_page_number }}{{ getvars }}" class="next">{% trans "next" %} ››</a> {% else %} <span class="disabled next">{% trans "next" %} ››</span> {% endif %} diff --git a/pagination/templatetags/pagination_tags.py b/pagination/templatetags/pagination_tags.py index ae843b1..c115720 100644 --- a/pagination/templatetags/pagination_tags.py +++ b/pagination/templatetags/pagination_tags.py @@ -4,6 +4,7 @@ except NameError: from sets import Set as set from django import template +from django.template import TOKEN_BLOCK from django.http import Http404 from django.core.paginator import Paginator, InvalidPage from django.conf import settings @@ -20,6 +21,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 + split = token.split_contents() as_index = None context_var = None @@ -36,10 +43,10 @@ def do_autopaginate(parser, token): "context_var_name %%}" % split[0]) del split[as_index:as_index + 2] if len(split) == 2: - return AutoPaginateNode(split[1]) + return AutoPaginateNode(split[1], multiple_paginations=multiple_paginations) elif len(split) == 3: return AutoPaginateNode(split[1], paginate_by=split[2], - context_var=context_var) + context_var=context_var, multiple_paginations=multiple_paginations) elif len(split) == 4: try: orphans = int(split[3]) @@ -47,7 +54,7 @@ def do_autopaginate(parser, token): raise template.TemplateSyntaxError(u'Got %s, but expected integer.' % split[3]) return AutoPaginateNode(split[1], paginate_by=split[2], orphans=orphans, - context_var=context_var) + context_var=context_var, multiple_paginations=multiple_paginations) else: raise template.TemplateSyntaxError('%r tag takes one required ' + 'argument and one optional argument' % split[0]) @@ -69,7 +76,7 @@ class AutoPaginateNode(template.Node): tag. If you choose not to use *{% paginate %}*, make sure to display the list of available pages, or else the application may seem to be buggy. """ - def __init__(self, queryset_var, paginate_by=DEFAULT_PAGINATION, + def __init__(self, queryset_var, multiple_paginations, paginate_by=DEFAULT_PAGINATION, orphans=DEFAULT_ORPHANS, context_var=None): self.queryset_var = template.Variable(queryset_var) if isinstance(paginate_by, int): @@ -78,8 +85,14 @@ class AutoPaginateNode(template.Node): self.paginate_by = template.Variable(paginate_by) self.orphans = orphans self.context_var = context_var + self.multiple_paginations = multiple_paginations def render(self, context): + if self.multiple_paginations or context.has_key('paginator'): + page_suffix = '_%s' % self.queryset_var + else: + page_suffix = '' + key = self.queryset_var.var value = self.queryset_var.resolve(context) if isinstance(self.paginate_by, int): @@ -88,7 +101,7 @@ class AutoPaginateNode(template.Node): paginate_by = self.paginate_by.resolve(context) paginator = Paginator(value, paginate_by, self.orphans) try: - page_obj = paginator.page(context['request'].page) + page_obj = paginator.page(context['request'].page(page_suffix)) except InvalidPage: if INVALID_PAGE_RAISES_404: raise Http404('Invalid page requested. If DEBUG were set to ' + @@ -102,10 +115,10 @@ class AutoPaginateNode(template.Node): context[key] = page_obj.object_list context['paginator'] = paginator context['page_obj'] = page_obj + context['page_suffix'] = page_suffix return u'' - -def paginate(context, window=DEFAULT_WINDOW, hashtag=''): +def paginate(context, window=DEFAULT_WINDOW): """ Renders the ``pagination/pagination.html`` template, resulting in a Digg-like display of the available pages, given the current page. If there @@ -133,12 +146,8 @@ def paginate(context, window=DEFAULT_WINDOW, hashtag=''): try: paginator = context['paginator'] page_obj = context['page_obj'] + page_suffix = context.get('page_suffix', '') page_range = paginator.page_range - # Calculate the record range in the current page for display. - records = {'first': 1 + (page_obj.number - 1) * paginator.per_page} - records['last'] = records['first'] + paginator.per_page - 1 - if records['last'] + paginator.orphans >= paginator.count: - records['last'] = paginator.count # First and last are simply the first *n* pages and the last *n* pages, # where *n* is the current window size. first = set(page_range[:window]) @@ -205,18 +214,16 @@ def paginate(context, window=DEFAULT_WINDOW, hashtag=''): differenced.sort() pages.extend(differenced) to_return = { - 'MEDIA_URL': settings.MEDIA_URL, 'pages': pages, - 'records': records, 'page_obj': page_obj, 'paginator': paginator, - 'hashtag': hashtag, 'is_paginated': paginator.count > paginator.per_page, + 'page_suffix': page_suffix, } if 'request' in context: getvars = context['request'].GET.copy() - if 'page' in getvars: - del getvars['page'] + if 'page%s' % page_suffix in getvars: + del getvars['page%s' % page_suffix] if len(getvars.keys()) > 0: to_return['getvars'] = "&%s" % getvars.urlencode() else: diff --git a/pagination/tests.py b/pagination/tests.py index 31b3301..454e19d 100644 --- a/pagination/tests.py +++ b/pagination/tests.py @@ -4,22 +4,8 @@ >>> 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'] +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['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'] @@ -39,28 +25,18 @@ [1, 2] >>> p = Paginator(range(21), 2, 1) ->>> pg = paginate({'paginator': p, 'page_obj': p.page(1)}) ->>> pg['pages'] +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['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 +>>> 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 = 1 +... page = lambda self, suffix: 1 >>> t.render(Context({'var': range(21), 'request': HttpRequest()})) u'\\n\\n<div class="pagination">... @@ -73,11 +49,15 @@ u'\\n\\n<div class="pagination">... u'\\n\\n<div class="pagination">... >>> t = Template("{% load pagination_tags %}{% autopaginate var by %}{% paginate %}") >>> t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()})) -u'\\n\\n<div class="pagination">... +u'\\n\\n<div class="pagination">...<a href="?page=2"... >>> t = Template("{% load pagination_tags %}{% autopaginate var by as foo %}{{ foo }}") >>> t.render(Context({'var': range(21), 'by': 20, 'request': HttpRequest()})) u'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]' >>> +>>> t = Template("{% load pagination_tags %}{% autopaginate var2 by as foo2 %}{% paginate %}{% autopaginate var by as foo %}{% paginate %}") +>>> t.render(Context({'var': range(21), 'var2': range(50, 121), 'by': 20, 'request': HttpRequest()})) +u'\\n\\n<div class="pagination">...<a href="?page_var2=2"...<a href="?page_var=2"... +>>> # Testing InfinitePaginator @@ -155,4 +135,4 @@ True >>> request = WSGIRequest({'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart', 'wsgi.input': StringIO()}) >>> middleware.process_request(request) >>> request.upload_handlers.append('asdf') -""" +""" \ No newline at end of file