Ticket #6860: 0005-Improve-the-new-paginator.2.diff

File 0005-Improve-the-new-paginator.2.diff, 5.9 KB (added by Alberto García Hierro <fiam@…>, 16 years ago)

Improved version of the patch

  • django/core/paginator.py

    From 59a5d7527a4b5c40b322ec7aa3643c345793a58d Mon Sep 17 00:00:00 2001
    From: =?utf-8?q?Alberto=20Garc=C3=ADa=20Hierro?= <fiam@rm-fr.net>
    Date: Sun, 23 Mar 2008 05:18:27 +0100
    Subject: [PATCH] Improve the new paginator.
    
    Add methods for storing the base_url and retrieving it,
    displaying the page list as ul or div (taking the
    current page into account) as well as for obtaining
    the links for the previous and next pages.
    ---
     django/core/paginator.py |  106 +++++++++++++++++++++++++++++++++++++++++++++-
     1 files changed, 105 insertions(+), 1 deletions(-)
    
    diff --git a/django/core/paginator.py b/django/core/paginator.py
    index 04cc4bf..8683cde 100644
    a b  
     1from django.utils.translation import ugettext as _
     2from django.utils.safestring import mark_safe
     3from django.http import Http404
     4
    15class InvalidPage(Exception):
    26    pass
    37
     8class PageList(object):
     9    def __init__(self, paginator):
     10        self.curpage = paginator.page(paginator.curpage)
     11        self.adjacent_count = paginator.adjacent_count
     12
     13    def __repr__(self):
     14        return '<PageList current: %d - total: %d>' % \
     15            (self.curpage.paginator.curpage, self.curpage.paginator.num_pages)
     16
     17    def _add_range_as_element(self, open, close, start, end):
     18        markup = ''
     19        for i in range(start, end + 1):
     20            page = self.curpage.paginator.page(i)
     21            if self.curpage.number == i:
     22                markup += '%s<a class="curpage">%d</a>%s' % \
     23                    (open, i, close)
     24            else:
     25                markup += '%s<a href="%s">%d</a>%s' % \
     26                    (open, page.url(), i, close)
     27        return markup
     28
     29    def _as_html(self, el, subel_open, subel_close):
     30        if not self.curpage.has_other_pages():
     31            return u''
     32
     33        markup = '<%s class="pagelist">' % el
     34
     35        markup += '%s<%s class="prev-next">' % (subel_open, el)
     36        if self.curpage.has_previous():
     37            markup += '%s<a href="%s">&laquo; %s</a>%s' % \
     38                    (subel_open, self.curpage.previous_page_url(),
     39                    _('Previous'), subel_close)
     40        if self.curpage.has_next():
     41            markup += '%s<a href="%s">%s &raquo;</a>%s' % \
     42                    (subel_open, self.curpage.next_page_url(),
     43                    _('Next'), subel_close)
     44        markup += '</%s>%s' % (el, subel_close)
     45       
     46        num_pages = self.curpage.paginator.num_pages
     47        midstart = max(self.curpage.number - self.adjacent_count, 1)
     48        midend = min(self.curpage.number + self.adjacent_count, num_pages)
     49
     50        if midstart > 1:
     51            end = min(self.adjacent_count + 1, midstart - 1)
     52            markup += '%s<%s class="start">' % (subel_open, el)
     53            markup += self._add_range_as_element(subel_open,
     54                    subel_close, 1, end)
     55            markup += '</%s>%s' % (el, subel_close)
     56
     57        markup += '%s<%s class="middle">' % (subel_open, el)
     58        markup += self._add_range_as_element(subel_open, subel_close,
     59                    midstart, midend)
     60        markup += '</%s>%s' % (el, subel_close)
     61
     62        if midend < num_pages:
     63            start = max(num_pages - self.adjacent_count, midend + 1)
     64            markup += '%s<%s class="end">' % (subel_open, el)
     65            markup += self._add_range_as_element(subel_open, subel_close,
     66                    start, self.curpage.paginator.num_pages)
     67            markup += '</%s>%s' % (el, subel_close)
     68
     69        markup += '</%s>' % el
     70
     71        return mark_safe(markup)
     72
     73    def as_ul(self):
     74        return self._as_html('ul', '<li>', '</li>')
     75
     76    def as_div(self):
     77        return self._as_html('div', '', '')
     78
     79
    480class Paginator(object):
    5     def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
     81    def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True, base_url=None, page_suffix=None, adjacent_count=2, current=None):
    682        self.object_list = object_list
    783        self.per_page = per_page
    884        self.orphans = orphans
    985        self.allow_empty_first_page = allow_empty_first_page
     86        self.base_url = base_url
     87        self.page_suffix = page_suffix
     88        self.curpage = current
     89        self.adjacent_count = adjacent_count
    1090        self._num_pages = self._count = None
    1191
    1292    def validate_number(self, number):
    class Paginator(object):  
    31111        top = bottom + self.per_page
    32112        if top + self.orphans >= self.count:
    33113            top = self.count
     114        if self.curpage is None:
     115            self.curpage = number
    34116        return Page(self.object_list[bottom:top], number, self)
    35117
     118    def page_or_404(self, number):
     119        try:
     120            return self.page(number)
     121        except InvalidPage:
     122            raise Http404(_('Invalid page'))
     123
    36124    def _get_count(self):
    37125        "Returns the total number of objects, across all pages."
    38126        if self._count is None:
    class Paginator(object):  
    61149        return range(1, self.num_pages + 1)
    62150    page_range = property(_get_page_range)
    63151
     152    def _get_page_list(self):
     153        return PageList(self)
     154    page_list = property(_get_page_list)
     155
    64156class QuerySetPaginator(Paginator):
    65157    """
    66158    Like Paginator, but works on QuerySets.
    class Page(object):  
    95187    def previous_page_number(self):
    96188        return self.number - 1
    97189
     190    def next_page_url(self):
     191        return Page(self.object_list, self.number + 1, self.paginator).url()
     192
     193    def previous_page_url(self):
     194        return Page(self.object_list, self.number - 1, self.paginator).url()
     195
     196    def url(self):
     197        if self.number == 1:
     198            return self.paginator.base_url
     199
     200        return self.paginator.base_url + self.paginator.page_suffix % self.number
     201
    98202    def start_index(self):
    99203        """
    100204        Returns the 1-based index of the first object on this page,
Back to Top