|
1 #!/usr/bin/python2.5 |
|
2 # |
|
3 # Copyright 2008 the Melange authors. |
|
4 # |
|
5 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 # you may not use this file except in compliance with the License. |
|
7 # You may obtain a copy of the License at |
|
8 # |
|
9 # http://www.apache.org/licenses/LICENSE-2.0 |
|
10 # |
|
11 # Unless required by applicable law or agreed to in writing, software |
|
12 # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 # See the License for the specific language governing permissions and |
|
15 # limitations under the License. |
|
16 |
|
17 """Helpers used to render lists. |
|
18 """ |
|
19 |
|
20 __authors__ = [ |
|
21 '"Chen Lunpeng" <forever.clp@gmail.com>', |
|
22 '"Pawel Solyga" <pawel.solyga@gmail.com>', |
|
23 ] |
|
24 |
|
25 |
|
26 from soc.views.helpers import forms_helpers |
|
27 |
|
28 |
|
29 DEF_PAGINATION = 10 |
|
30 MAX_PAGINATION = 100 |
|
31 |
|
32 DEF_PAGINATION_CHOICES = ( |
|
33 ('10', '10 items per page'), |
|
34 ('25', '25 items per page'), |
|
35 ('50', '50 items per page'), |
|
36 ('100', '100 items per page'), |
|
37 ) |
|
38 |
|
39 |
|
40 def getPreferredListPagination(user=None): |
|
41 """Returns User's preferred list pagination limit. |
|
42 |
|
43 Args: |
|
44 user: User entity containing the list pagination preference; |
|
45 default is None, to use the current logged-in User |
|
46 """ |
|
47 # TODO: eventually this limit should be a User profile preference |
|
48 # (stored in the site-wide User Model) preference |
|
49 return DEF_PAGINATION |
|
50 |
|
51 |
|
52 def cleanListParameters(offset=None, limit=None): |
|
53 """Converts and validates offset and limit values of the list. |
|
54 |
|
55 Args: |
|
56 offset: offset in list which defines first item to return |
|
57 limit: max amount of items per page |
|
58 |
|
59 Returns: |
|
60 updated offset and limit values |
|
61 """ |
|
62 # update offset value |
|
63 try: |
|
64 offset = int(offset) |
|
65 except: |
|
66 # also catches offset=None case where offset not supplied |
|
67 offset = 0 |
|
68 |
|
69 # update limit value |
|
70 try: |
|
71 limit = int(limit) |
|
72 except: |
|
73 # also catches limit=None case where limit not supplied |
|
74 limit = getPreferredListPagination() |
|
75 |
|
76 return max(0, offset), max(1, min(limit, MAX_PAGINATION)) |
|
77 |
|
78 |
|
79 DEF_LIST_TEMPLATES = {'list_main': 'soc/list/list_main.html', |
|
80 'list_pagination': 'soc/list/list_pagination.html', |
|
81 'list_row': 'soc/list/list_row.html', |
|
82 'list_heading': 'soc/list/list_heading.html'} |
|
83 |
|
84 def setList(request, context, list_data, |
|
85 offset=0, limit=0, list_templates=DEF_LIST_TEMPLATES): |
|
86 """Updates template context dict with variables used for rendering lists. |
|
87 |
|
88 Args: |
|
89 request: the Django HTTP request object |
|
90 context: the template context dict to be updated in-place (pass in a copy |
|
91 if the original must not be modified), or None if a new one is to be |
|
92 created; any existing fields already present in the context dict passed |
|
93 in by the caller are left unaltered |
|
94 list_data: array of data to be displayed in the list |
|
95 offset: offset in list which defines first item to return |
|
96 limit: max amount of items per page |
|
97 list_templates: templates that are used when rendering list |
|
98 |
|
99 Returns: |
|
100 updated template context dict supplied by the caller or a new context |
|
101 dict if the caller supplied None |
|
102 |
|
103 { |
|
104 'list_data': list data to be displayed |
|
105 'list_main': url to list main template |
|
106 'list_pagination': url to list pagination template |
|
107 'list_row': url to list row template |
|
108 'list_heading': url to list heading template |
|
109 'limit': max amount of items per page, |
|
110 'newest': url to first page of the list |
|
111 'prev': url to previous page |
|
112 'next': url to next page |
|
113 'first': offset of the first item in the list |
|
114 'last': offest of the lst item in the list |
|
115 } |
|
116 """ |
|
117 if not list_data: |
|
118 list_data = [] |
|
119 |
|
120 more = bool(list_data[limit:]) |
|
121 if more: |
|
122 del list_data[limit:] |
|
123 if more: |
|
124 next = request.path + '?offset=%d&limit=%d' % (offset+limit, limit) |
|
125 else: |
|
126 next = '' |
|
127 if offset > 0: |
|
128 prev = request.path + '?offset=%d&limit=%d' % (max(0, offset-limit), limit) |
|
129 else: |
|
130 prev = '' |
|
131 newest = '' |
|
132 if offset > limit: |
|
133 newest = request.path + '?limit=%d' % limit |
|
134 |
|
135 if not context: |
|
136 context = {} |
|
137 |
|
138 context.update( |
|
139 {'list_data': list_data, |
|
140 'list_main': list_templates['list_main'], |
|
141 'list_pagination': list_templates['list_pagination'], |
|
142 'list_row': list_templates['list_row'], |
|
143 'list_heading': list_templates['list_heading'], |
|
144 'limit': limit, |
|
145 'newest': newest, |
|
146 'prev': prev, |
|
147 'next': next, |
|
148 'first': offset+1, |
|
149 'last': len(list_data) > 1 and offset+len(list_data) or None}) |
|
150 |
|
151 return context |
|
152 |
|
153 |
|
154 def makePaginationForm( |
|
155 request, limit, arg_name='limit', choices=DEF_PAGINATION_CHOICES, |
|
156 field_name_fmt=forms_helpers.DEF_SELECT_QUERY_ARG_FIELD_NAME_FMT): |
|
157 """Returns a customized pagination limit selection form. |
|
158 |
|
159 Args: |
|
160 request: the standard Django HTTP request object |
|
161 limit: the initial value of the selection control |
|
162 arg_name: see forms_helpers.makeSelectQueryArgForm(); default is 'limit' |
|
163 choices: see forms_helpers.makeSelectQueryArgForm(); default is |
|
164 DEF_PAGINATION_CHOICES |
|
165 field_name_fmt: see forms_helpers.makeSelectQueryArgForm() |
|
166 """ |
|
167 choices = makeNewPaginationChoices(limit=limit, choices=choices) |
|
168 |
|
169 return forms_helpers.makeSelectQueryArgForm( |
|
170 request, arg_name, limit, choices) |
|
171 |
|
172 |
|
173 def makeNewPaginationChoices(limit=DEF_PAGINATION, |
|
174 choices=DEF_PAGINATION_CHOICES): |
|
175 """Updates the pagination limit selection form. |
|
176 |
|
177 Args: |
|
178 limit: the initial value of the selection control; |
|
179 default is DEF_PAGINATION |
|
180 choices: see forms_helpers.makeSelectQueryArgForm(); |
|
181 default is DEF_PAGINATION_CHOICES |
|
182 |
|
183 Returns: |
|
184 a new pagination choices list if limit is not in |
|
185 DEF_PAGINATION_CHOICES, or DEF_PAGINATION_CHOICES otherwise |
|
186 """ |
|
187 # determine where to insert the new limit into choices |
|
188 new_choices = [] |
|
189 inserted = False |
|
190 |
|
191 for pagination, label in choices: |
|
192 items = int(pagination) |
|
193 |
|
194 if limit == items: |
|
195 # limit is already present, so just return existing choices |
|
196 return choices |
|
197 |
|
198 if (not inserted) and (limit < items): |
|
199 # limit needs to be inserted before the current pagination, |
|
200 # so assemble a new choice tuple and append it |
|
201 choice = (str(limit), '%s items per page' % limit) |
|
202 new_choices.append(choice) |
|
203 inserted = True |
|
204 |
|
205 # append the existing choice |
|
206 new_choices.append((pagination, label)) |
|
207 |
|
208 if not inserted: |
|
209 # new choice must go last, past all other existing choices |
|
210 choice = (str(limit), '%s items per page' % limit) |
|
211 new_choices.append(choice) |
|
212 |
|
213 return new_choices |