Code

Ticket #2367: date_based_pagination.diff

File date_based_pagination.diff, 11.8 KB (added by paolo@…, 7 years ago)

pagination for each date_based

Line 
1Index: date_based.py
2===================================================================
3--- date_based.py       (revision 4741)
4+++ date_based.py       (working copy)
5@@ -1,14 +1,45 @@
6 from django.template import loader, RequestContext
7 from django.core.exceptions import ObjectDoesNotExist
8 from django.core.xheaders import populate_xheaders
9+from django.core.paginator import ObjectPaginator, InvalidPage
10 from django.db.models.fields import DateTimeField
11 from django.http import Http404, HttpResponse
12 import datetime, time
13 
14+def compute_pagination(request, paginator, page, paginate_by):
15+    """
16+    Compute queryset considering pagination, and update the context.
17+    """
18+    if not page:
19+        page = request.GET.get('page', 1)
20+    try:
21+        page = int(page)
22+        queryset = paginator.get_page(page - 1)
23+    except (InvalidPage, ValueError):
24+        if page == 1 and allow_empty:
25+            queryset = []
26+        else:
27+            raise Http404
28+
29+    c = {}
30+    c['is_paginated'] = paginator.pages > 1
31+    c['results_per_page'] = paginate_by
32+    c['has_next'] = paginator.has_next_page(page - 1)
33+    c['has_previous'] = paginator.has_previous_page(page - 1)
34+    c['page'] = page
35+    c['next'] = page + 1
36+    c['previous'] = page - 1
37+    c['last_on_page'] = paginator.last_on_page(page - 1),
38+    c['first_on_page'] = paginator.first_on_page(page - 1),
39+    c['pages'] = paginator.pages
40+    c['hits'] = paginator.hits
41+
42+    return (queryset, c)
43+
44 def archive_index(request, queryset, date_field, num_latest=15,
45         template_name=None, template_loader=loader,
46         extra_context=None, allow_empty=False, context_processors=None,
47-        mimetype=None, allow_future=False):
48+        mimetype=None, allow_future=False, paginate_by=None, page=None):
49     """
50     Generic top-level archive of date-based objects.
51 
52@@ -18,6 +49,30 @@
53             List of years
54         latest
55             Latest N (defaults to 15) objects by date
56+        is_paginated
57+            are the results paginated?
58+        results_per_page
59+            number of objects per page (if paginated)
60+        has_next
61+            is there a next page?
62+        has_previous
63+            is there a prev page?
64+        page
65+            the current page
66+        next
67+            the next page
68+        previous
69+            the previous page
70+        pages
71+            number of pages, total
72+        hits
73+            number of objects, total
74+        last_on_page
75+            the result number of the last of object in the
76+            object_list (1-indexed)
77+        first_on_page
78+            the result number of the first object in the
79+            object_list (1-indexed)
80     """
81     if extra_context is None: extra_context = {}
82     model = queryset.model
83@@ -30,8 +85,14 @@
84     if date_list and num_latest:
85         latest = queryset.order_by('-'+date_field)[:num_latest]
86     else:
87-        latest = None
88+        latest = []
89 
90+    # Pagination.
91+    pagination_context = {'is_paginated': False}
92+    if paginate_by:
93+        paginator = ObjectPaginator(latest, paginate_by)
94+        latest, pagination_context = compute_pagination(request, paginator, page, paginate_by)
95+
96     if not template_name:
97         template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
98     t = template_loader.get_template(template_name)
99@@ -44,12 +105,15 @@
100             c[key] = value()
101         else:
102             c[key] = value
103+
104+    c.update(pagination_context)
105+
106     return HttpResponse(t.render(c), mimetype=mimetype)
107 
108 def archive_year(request, year, queryset, date_field, template_name=None,
109         template_loader=loader, extra_context=None, allow_empty=False,
110         context_processors=None, template_object_name='object', mimetype=None,
111-        make_object_list=False, allow_future=False):
112+        make_object_list=False, allow_future=False, paginate_by=None, page=None):
113     """
114     Generic yearly archive view.
115 
116@@ -61,7 +125,33 @@
117             This year
118         object_list
119             List of objects published in the given month
120+
121             (Only available if make_object_list argument is True)
122+
123+        is_paginated
124+            are the results paginated?
125+        results_per_page
126+            number of objects per page (if paginated)
127+        has_next
128+            is there a next page?
129+        has_previous
130+            is there a prev page?
131+        page
132+            the current page
133+        next
134+            the next page
135+        previous
136+            the previous page
137+        pages
138+            number of pages, total
139+        hits
140+            number of objects, total
141+        last_on_page
142+            the result number of the last of object in the
143+            object_list (1-indexed)
144+        first_on_page
145+            the result number of the first object in the
146+            object_list (1-indexed)
147     """
148     if extra_context is None: extra_context = {}
149     model = queryset.model
150@@ -79,6 +169,13 @@
151         object_list = queryset.filter(**lookup_kwargs).order_by(date_field)
152     else:
153         object_list = []
154+
155+    # Pagination.
156+    pagination_context = {'is_paginated': False}
157+    if paginate_by:
158+        paginator = ObjectPaginator(object_list, paginate_by)
159+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
160+
161     if not template_name:
162         template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
163     t = template_loader.get_template(template_name)
164@@ -92,12 +189,16 @@
165             c[key] = value()
166         else:
167             c[key] = value
168+
169+    c.update(pagination_context)
170+
171     return HttpResponse(t.render(c), mimetype=mimetype)
172 
173 def archive_month(request, year, month, queryset, date_field,
174         month_format='%b', template_name=None, template_loader=loader,
175         extra_context=None, allow_empty=False, context_processors=None,
176-        template_object_name='object', mimetype=None, allow_future=False):
177+        template_object_name='object', mimetype=None, allow_future=False,
178+        paginate_by=None, page=None):
179     """
180     Generic monthly archive view.
181 
182@@ -111,6 +212,30 @@
183             (date) the first day of the previous month
184         object_list:
185             list of objects published in the given month
186+        is_paginated
187+            are the results paginated?
188+        results_per_page
189+            number of objects per page (if paginated)
190+        has_next
191+            is there a next page?
192+        has_previous
193+            is there a prev page?
194+        page
195+            the current page
196+        next
197+            the next page
198+        previous
199+            the previous page
200+        pages
201+            number of pages, total
202+        hits
203+            number of objects, total
204+        last_on_page
205+            the result number of the last of object in the
206+            object_list (1-indexed)
207+        first_on_page
208+            the result number of the first object in the
209+            object_list (1-indexed)
210     """
211     if extra_context is None: extra_context = {}
212     try:
213@@ -144,6 +269,12 @@
214     else:
215         next_month = None
216 
217+    # Pagination.
218+    pagination_context = {'is_paginated': False}
219+    if paginate_by:
220+        paginator = ObjectPaginator(object_list, paginate_by)
221+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
222+
223     if not template_name:
224         template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
225     t = template_loader.get_template(template_name)
226@@ -158,12 +289,16 @@
227             c[key] = value()
228         else:
229             c[key] = value
230+
231+    c.update(pagination_context)
232+
233     return HttpResponse(t.render(c), mimetype=mimetype)
234 
235 def archive_week(request, year, week, queryset, date_field,
236         template_name=None, template_loader=loader,
237         extra_context=None, allow_empty=True, context_processors=None,
238-        template_object_name='object', mimetype=None, allow_future=False):
239+        template_object_name='object', mimetype=None, allow_future=False,
240+        paginate_by=None, page=None):
241     """
242     Generic weekly archive view.
243 
244@@ -173,6 +308,30 @@
245             (date) this week
246         object_list:
247             list of objects published in the given week
248+        is_paginated
249+            are the results paginated?
250+        results_per_page
251+            number of objects per page (if paginated)
252+        has_next
253+            is there a next page?
254+        has_previous
255+            is there a prev page?
256+        page
257+            the current page
258+        next
259+            the next page
260+        previous
261+            the previous page
262+        pages
263+            number of pages, total
264+        hits
265+            number of objects, total
266+        last_on_page
267+            the result number of the last of object in the
268+            object_list (1-indexed)
269+        first_on_page
270+            the result number of the first object in the
271+            object_list (1-indexed)
272     """
273     if extra_context is None: extra_context = {}
274     try:
275@@ -194,6 +353,13 @@
276     object_list = queryset.filter(**lookup_kwargs)
277     if not object_list and not allow_empty:
278         raise Http404
279+
280+    # Pagination.
281+    pagination_context = {'is_paginated': False}
282+    if paginate_by:
283+        paginator = ObjectPaginator(object_list, paginate_by)
284+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
285+
286     if not template_name:
287         template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
288     t = template_loader.get_template(template_name)
289@@ -206,13 +372,16 @@
290             c[key] = value()
291         else:
292             c[key] = value
293+
294+    c.update(pagination_context)
295+
296     return HttpResponse(t.render(c), mimetype=mimetype)
297 
298 def archive_day(request, year, month, day, queryset, date_field,
299         month_format='%b', day_format='%d', template_name=None,
300         template_loader=loader, extra_context=None, allow_empty=False,
301         context_processors=None, template_object_name='object',
302-        mimetype=None, allow_future=False):
303+        mimetype=None, allow_future=False, paginate_by=None, page=None):
304     """
305     Generic daily archive view.
306 
307@@ -226,6 +395,30 @@
308             (datetime) the previous day
309         next_day
310             (datetime) the next day, or None if the current day is today
311+        is_paginated
312+            are the results paginated?
313+        results_per_page
314+            number of objects per page (if paginated)
315+        has_next
316+            is there a next page?
317+        has_previous
318+            is there a prev page?
319+        page
320+            the current page
321+        next
322+            the next page
323+        previous
324+            the previous page
325+        pages
326+            number of pages, total
327+        hits
328+            number of objects, total
329+        last_on_page
330+            the result number of the last of object in the
331+            object_list (1-indexed)
332+        first_on_page
333+            the result number of the first object in the
334+            object_list (1-indexed)
335     """
336     if extra_context is None: extra_context = {}
337     try:
338@@ -256,6 +449,12 @@
339     else:
340         next_day = None
341 
342+    # Pagination.
343+    pagination_context = {'is_paginated': False}
344+    if paginate_by:
345+        paginator = ObjectPaginator(object_list, paginate_by)
346+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
347+
348     if not template_name:
349         template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
350     t = template_loader.get_template(template_name)
351@@ -270,6 +469,9 @@
352             c[key] = value()
353         else:
354             c[key] = value
355+
356+    c.update(pagination_context)
357+
358     return HttpResponse(t.render(c), mimetype=mimetype)
359 
360 def archive_today(request, **kwargs):