paging maintains other GET parameters -- contributed by jezdez
[django-pagination.git] / pagination / templatetags / pagination_tags.py
1 try:
2     set
3 except NameError:
4     from sets import Set as set
5 from django import template
6 from pagination.registration import get_registry, default_pagination
7 registry = get_registry()
8 from django.db.models.query import QuerySet
9 from django.core.paginator import Paginator, QuerySetPaginator, InvalidPage
10 #from django.template.loader import render_to_string
11
12 register = template.Library()
13
14 def do_autopaginate(parser, token):
15     split = token.split_contents()
16     if len(split) == 1:
17         return AutoPaginateNode()
18     elif len(split) == 2:
19         return AutoPaginateNode(queryset_var=split[1])
20     else:
21         raise template.TemplateSyntaxError('%r tag takes only one optional argument.' % split[0])
22
23 class AutoPaginateNode(template.Node):
24     def __init__(self, queryset_var=None):
25         if queryset_var:
26             self.queryset_var = template.Variable(queryset_var)
27         else:
28             self.queryset_var = None
29
30     def render(self, context):
31         if self.queryset_var is not None:
32             try:
33                 key = self.queryset_var.var
34                 value = self.queryset_var.resolve(context)
35                 if issubclass(value.__class__, QuerySet):
36                     model = value.model
37                     paginator_class = QuerySetPaginator
38                 else:
39                     value = list(value)
40                     try:
41                         model = value[0].__class__
42                     except IndexError:
43                         return u''
44                     paginator_class = Paginator
45                 pagination = registry.get_for_model(model)
46                 if pagination is None:
47                     pagination = default_pagination
48                 paginator = paginator_class(value, pagination)
49                 try:
50                     page_obj = paginator.page(context['request'].page)
51                 except:
52                     return u''
53                 context[key] = page_obj.object_list
54                 context['paginator'] = paginator
55                 context['page_obj'] = page_obj
56                 return u''
57             except template.VariableDoesNotExist:
58                 pass
59         for d in context:
60             for key, value in d.iteritems():
61                 if issubclass(value.__class__, QuerySet):
62                     model = value.model
63                     pagination = registry.get_for_model(model)
64                     if pagination is not None:
65                         paginator = QuerySetPaginator(value, pagination)
66                         try:
67                             page_obj = paginator.page(context['request'].page)
68                         except:
69                             return u''
70                         context[key] = page_obj.object_list
71                         context['paginator'] = paginator
72                         context['page_obj'] = page_obj
73                         return u''
74         return u''
75
76 def paginate(context, window=4):
77     try:
78         paginator = context['paginator']
79         page_obj = context['page_obj']
80         page_range = paginator.page_range
81         first = set(page_range[:window])
82         last = set(page_range[-window:])
83         current_start = page_obj.number-1-window
84         if current_start < 0:
85             current_start = 0
86         current_end = page_obj.number-1+window
87         if current_end < 0:
88             current_end = 0
89         current = set(page_range[current_start:current_end])
90         pages = []
91         if len(first.intersection(current)) == 0:
92             first_list = sorted(list(first))
93             second_list = sorted(list(current))
94             pages.extend(first_list)
95             diff = second_list[0] - first_list[-1] 
96             if diff == 2:
97                 pages.append(second_list[0] - 1)
98             elif diff == 1:
99                 pass
100             else:
101                 pages.append(None)
102             pages.extend(second_list)
103         else:
104             pages.extend(sorted(list(first.union(current))))
105         if len(current.intersection(last)) == 0:
106             second_list = sorted(list(last))
107             diff = second_list[0] - pages[-1]
108             if diff == 2:
109                 pages.append(second_list[0] - 1)
110             elif diff == 1:
111                 pass
112             else:
113                 pages.append(None)
114             pages.extend(second_list)
115         else:
116             pages.extend(sorted(list(last.difference(current))))
117         
118         getvars = context['request'].GET.copy()
119         if 'page' in getvars:
120             del getvars['page']
121         return {
122             'pages': pages,
123             'page_obj': page_obj,
124             'paginator': paginator,
125             'is_paginated': paginator.count > paginator.per_page,
126             'getvars': "&%s" % getvars.urlencode()
127         }
128     except KeyError:
129         return u''
130 register.inclusion_tag('pagination/pagination.html', takes_context=True)(paginate)
131 register.tag('autopaginate', do_autopaginate)