Django

Code

root/django/branches/newforms-admin/django/core/paginator.py

Revision 7881, 6.3 kB (checked in by brosner, 5 months ago)

newforms-admin: Merged from trunk up to [7877].

  • Property svn:eol-style set to native
  • Property svn:keywords set to LastChangedRevision
Line 
1 class InvalidPage(Exception):
2     pass
3
4 class PageNotAnInteger(InvalidPage):
5     pass
6
7 class EmptyPage(InvalidPage):
8     pass
9
10 class Paginator(object):
11     def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
12         self.object_list = object_list
13         self.per_page = per_page
14         self.orphans = orphans
15         self.allow_empty_first_page = allow_empty_first_page
16         self._num_pages = self._count = None
17
18     def validate_number(self, number):
19         "Validates the given 1-based page number."
20         try:
21             number = int(number)
22         except ValueError:
23             raise PageNotAnInteger('That page number is not an integer')
24         if number < 1:
25             raise EmptyPage('That page number is less than 1')
26         if number > self.num_pages:
27             if number == 1 and self.allow_empty_first_page:
28                 pass
29             else:
30                 raise EmptyPage('That page contains no results')
31         return number
32
33     def page(self, number):
34         "Returns a Page object for the given 1-based page number."
35         number = self.validate_number(number)
36         bottom = (number - 1) * self.per_page
37         top = bottom + self.per_page
38         if top + self.orphans >= self.count:
39             top = self.count
40         return Page(self.object_list[bottom:top], number, self)
41
42     def _get_count(self):
43         "Returns the total number of objects, across all pages."
44         if self._count is None:
45             from django.db.models.query import QuerySet
46             if isinstance(self.object_list, QuerySet):
47                 self._count = self.object_list.count()
48             else:
49                 self._count = len(self.object_list)
50         return self._count
51     count = property(_get_count)
52
53     def _get_num_pages(self):
54         "Returns the total number of pages."
55         if self._num_pages is None:
56             hits = self.count - 1 - self.orphans
57             if hits < 1:
58                 hits = 0
59             if hits == 0 and not self.allow_empty_first_page:
60                 self._num_pages = 0
61             else:
62                 self._num_pages = hits // self.per_page + 1
63         return self._num_pages
64     num_pages = property(_get_num_pages)
65
66     def _get_page_range(self):
67         """
68         Returns a 1-based range of pages for iterating through within
69         a template for loop.
70         """
71         return range(1, self.num_pages + 1)
72     page_range = property(_get_page_range)
73
74 QuerySetPaginator = Paginator # For backwards-compatibility.
75
76 class Page(object):
77     def __init__(self, object_list, number, paginator):
78         self.object_list = object_list
79         self.number = number
80         self.paginator = paginator
81
82     def __repr__(self):
83         return '<Page %s of %s>' % (self.number, self.paginator.num_pages)
84
85     def has_next(self):
86         return self.number < self.paginator.num_pages
87
88     def has_previous(self):
89         return self.number > 1
90
91     def has_other_pages(self):
92         return self.has_previous() or self.has_next()
93
94     def next_page_number(self):
95         return self.number + 1
96
97     def previous_page_number(self):
98         return self.number - 1
99
100     def start_index(self):
101         """
102         Returns the 1-based index of the first object on this page,
103         relative to total objects in the paginator.
104         """
105         return (self.paginator.per_page * (self.number - 1)) + 1
106
107     def end_index(self):
108         """
109         Returns the 1-based index of the last object on this page,
110         relative to total objects found (hits).
111         """
112         if self.number == self.paginator.num_pages:
113             return self.paginator.count
114         return self.number * self.paginator.per_page
115
116 class ObjectPaginator(Paginator):
117     """
118     Legacy ObjectPaginator class, for backwards compatibility.
119
120     Note that each method on this class that takes page_number expects a
121     zero-based page number, whereas the new API (Paginator/Page) uses one-based
122     page numbers.
123     """
124     def __init__(self, query_set, num_per_page, orphans=0):
125         Paginator.__init__(self, query_set, num_per_page, orphans)
126         import warnings
127         warnings.warn("The ObjectPaginator is deprecated. Use django.core.paginator.Paginator instead.", DeprecationWarning)
128
129         # Keep these attributes around for backwards compatibility.
130         self.query_set = query_set
131         self.num_per_page = num_per_page
132         self._hits = self._pages = None
133
134     def validate_page_number(self, page_number):
135         try:
136             page_number = int(page_number) + 1
137         except ValueError:
138             raise PageNotAnInteger
139         return self.validate_number(page_number)
140
141     def get_page(self, page_number):
142         try:
143             page_number = int(page_number) + 1
144         except ValueError:
145             raise PageNotAnInteger
146         return self.page(page_number).object_list
147
148     def has_next_page(self, page_number):
149         return page_number < self.pages - 1
150
151     def has_previous_page(self, page_number):
152         return page_number > 0
153
154     def first_on_page(self, page_number):
155         """
156         Returns the 1-based index of the first object on the given page,
157         relative to total objects found (hits).
158         """
159         page_number = self.validate_page_number(page_number)
160         return (self.num_per_page * (page_number - 1)) + 1
161
162     def last_on_page(self, page_number):
163         """
164         Returns the 1-based index of the last object on the given page,
165         relative to total objects found (hits).
166         """
167         page_number = self.validate_page_number(page_number)
168         if page_number == self.num_pages:
169             return self.count
170         return page_number * self.num_per_page
171
172     def _get_count(self):
173         # The old API allowed for self.object_list to be either a QuerySet or a
174         # list. Here, we handle both.
175         if self._count is None:
176             try:
177                 self._count = self.object_list.count()
178             except (AttributeError, TypeError):
179                 # AttributeError if object_list has no count() method.
180                 # TypeError if object_list.count() requires arguments
181                 # (i.e. is of type list).
182                 self._count = len(self.object_list)
183         return self._count
184     count = property(_get_count)
185
186     # The old API called it "hits" instead of "count".
187     hits = count
188
189     # The old API called it "pages" instead of "num_pages".
190     pages = Paginator.num_pages
Note: See TracBrowser for help on using the browser.