Ticket #4805: 4805.diff

File 4805.diff, 9.0 KB (added by Gary Wilson <gary.wilson@…>, 12 years ago)
  • django/core/paginator.py

    === modified file 'django/core/paginator.py'
     
    1515    13 records, num_per_page=10, orphans=2 --> pages==2, len(self.get_page(0))==10
    1616    12 records, num_per_page=10, orphans=2 --> pages==1, len(self.get_page(0))==12
    1717    """
    18     def __init__(self, query_set, num_per_page, orphans=0):
     18   
     19    def __init__(self, query_set, num_per_page=10, orphans=0, page=1):
     20        """
     21        Initialize the ObjectPaginator instance.
     22       
     23        Parameters::
     24         * ``query_set`` -- A QuerySet or sequence of objects to paginate.
     25         * ``num_per_page`` -- The number of objects to put on a page.
     26                               By default, ``num_per_page`` is 10.
     27         * ``orphans`` -- The number of objects to not put by themselves on
     28                          the last page.  For example, if ``orphans`` is 2
     29                          and the total number of objects would normally
     30                          result in two items on the last page, place those
     31                          items on the previous page instead of leaving them
     32                          "dangling" on the last page.  By default,
     33                          ``orphans`` is 0.
     34         * ``page`` -- The page number to initialize the ObjectPaginator
     35                       instance to.  ``page`` is 1 by default, meaning that
     36                       the ObjectPaginator instance will start on the first
     37                       page.  ``page`` may be an integer or the string
     38                       representation of an interger, which is useful when
     39                       passing directly from a URL query string.
     40        """
    1941        self.query_set = query_set
    2042        self.num_per_page = num_per_page
    2143        self.orphans = orphans
    22         self._hits = self._pages = None
    23 
     44        self.page = page
     45   
     46    def _get_query_set(self):
     47        """
     48        Get the QuerySet or sequence of objects.
     49        """
     50        return self._query_set
     51   
     52    def _set_query_set(self, query_set):
     53        """
     54        Set the QuerySet or sequence of objects and clear the hits cache.
     55        """
     56        self._hits = None
     57        self._query_set = query_set
     58   
     59    query_set = property(_get_query_set, _set_query_set)
     60   
    2461    def validate_page_number(self, page_number):
     62        """
     63        Coerce the passed page_number to an integer and insure that the
     64        page exists.  Return the integer page number.
     65        """
    2566        try:
    2667            page_number = int(page_number)
    2768        except ValueError:
    2869            raise InvalidPage
    29         if page_number < 0 or page_number > self.pages - 1:
     70        if not self.has_page(page_number):
    3071            raise InvalidPage
    3172        return page_number
    32 
    33     def get_page(self, page_number):
     73   
     74    def _get_page(self):
     75        """
     76        Get the current page.
     77        """
     78        return self._page
     79       
     80    def _set_page(self, page_number):
     81        """
     82        Set the current page to the passed (1-based) page_number.
     83        Raise an InvalidPage exception if page_number is invalid.
     84        """
    3485        page_number = self.validate_page_number(page_number)
    35         bottom = page_number * self.num_per_page
    36         top = bottom + self.num_per_page
    37         if top + self.orphans >= self.hits:
    38             top = self.hits
    39         return self.query_set[bottom:top]
    40 
     86        self._page = page_number
     87   
     88    page = property(_get_page, _set_page)
     89   
     90    def _get_first_page(self):
     91        """
     92        Return the (1-based) page number of the first page.
     93        """
     94        return 1
     95   
     96    first_page = property(_get_first_page)
     97   
     98    def _get_last_page(self):
     99        """
     100        Return the (1-based) page number of the last page.
     101        """
     102        return self.pages
     103   
     104    last_page = property(_get_last_page)       
     105   
     106    def _get_pages(self):
     107        """
     108        Return the total number of pages.
     109        """
     110        hits = max(self.hits - self.orphans - 1, 0)
     111        return hits // self.num_per_page + 1
     112   
     113    pages = property(_get_pages)
     114   
     115    def has_page(self, page_number):
     116        """
     117        Return true if the paginator has the passed page_number, and False
     118        otherwise.
     119        """
     120        return self.first_page <= page_number <= self.last_page
     121   
     122    def next_page(self, page_number=None):
     123        """
     124        Return the page number of the page after the passed page_number.
     125        If page_number is not given, then use the current page.
     126        If there is no next page, then return None.
     127        """
     128        if page_number is None:
     129            page_number = self.page
     130        else:
     131            page_number = self.validate_page_number(page_number)
     132        next_page = self.page + 1
     133        if self.has_page(next_page):
     134            return next_page
     135   
    41136    def has_next_page(self, page_number):
    42         "Does page $page_number have a 'next' page?"
    43         return page_number < self.pages - 1
    44 
     137        """
     138        Return True if the passed page_number has a next page, and False
     139        otherwise.  If page_number is not given, then use the current page.
     140        """
     141        return self.next_page(page_number) is not None
     142   
     143    def previous_page(self, page_number=None):
     144        """
     145        Return the page number of the page before the passed page_number.
     146        If page_number is not given, then use the current page.
     147        If there is no previous page, then return None.
     148        """
     149        if page_number is None:
     150            page_number = self.page
     151        else:
     152            page_number = self.validate_page_number(page_number)
     153        previous_page = self.page - 1
     154        if self.has_page(previous_page):
     155            return previous_page
     156   
    45157    def has_previous_page(self, page_number):
    46         return page_number > 0
    47 
    48     def first_on_page(self, page_number):
     158        """
     159        Return True if the passed page_number has a previous page, and False
     160        otherwise.  If page_number is not given, then use the current page.
     161        """
     162        return self.previous_page(page_number) is not None
     163   
     164    def first_on_page(self, page_number=None):
    49165        """
    50166        Returns the 1-based index of the first object on the given page,
    51167        relative to total objects found (hits).
    52168        """
    53         page_number = self.validate_page_number(page_number)
    54         return (self.num_per_page * page_number) + 1
    55 
    56     def last_on_page(self, page_number):
     169        if page_number is None:
     170            page_number = self.page
     171        else:
     172            page_number = self.validate_page_number(page_number)
     173        return (page_number - 1) * self.num_per_page + 1
     174   
     175    def last_on_page(self, page_number=None):
    57176        """
    58177        Returns the 1-based index of the last object on the given page,
    59178        relative to total objects found (hits).
    60179        """
    61         page_number = self.validate_page_number(page_number)
    62         page_number += 1   # 1-base
    63         if page_number == self.pages:
     180        if page_number is None:
     181            page_number = self.page
     182        else:
     183            page_number = self.validate_page_number(page_number)
     184        # Last page is special because it can have orphans.
     185        if page_number is self.last_page:
    64186            return self.hits
    65187        return page_number * self.num_per_page
    66188
    67189    def _get_hits(self):
     190        """
     191        Return the number of objects in the paginator's QuerySet or sequence
     192        of objects.  First try to call .count() on self.query_set since
     193        this will usually be an actual QuerySet.  If that fails, then fall
     194        back to calling len(self.query_set).
     195        """
    68196        if self._hits is None:
    69197            # Try .count() or fall back to len().
    70198            try:
     
    76204                self._hits = len(self.query_set)
    77205        return self._hits
    78206
    79     def _get_pages(self):
    80         if self._pages is None:
    81             hits = (self.hits - 1 - self.orphans)
    82             if hits < 1:
    83                 hits = 0
    84             self._pages = hits // self.num_per_page + 1
    85         return self._pages
    86 
    87207    hits = property(_get_hits)
    88     pages = property(_get_pages)
     208
     209    def get_items(self, page_number=None):
     210        """
     211        Return the slice of items for the passed (1-based) page_number.
     212        If page_number is not given, then use the current page.
     213        """
     214        if page_number is None:
     215            page_number = self.page
     216        else:
     217            page_number = self.validate_page_number(page_number)
     218        bottom = (page_number - 1)* self.num_per_page
     219        # Special handling of orphans on the last page.
     220        if page_number is self.last_page:
     221            top = self.hits
     222        else:
     223            top = bottom + self.num_per_page
     224        return self.query_set[bottom:top]
     225   
     226    def get_page(self, page_number):
     227        """
     228        This function was kept to keep backwards compatibility.
     229        Return the slice of items for the passed (0-based) page_number.
     230        """
     231        return self.get_items(page_number + 1)
Back to Top