1 from django import http
2 from django.db.models import Count
3 from django.utils import simplejson as json
4 from django.utils.functional import Promise
5 from datetime import datetime
6 from functools import wraps
9 class ExtendedEncoder(json.JSONEncoder):
11 def default(self, obj):
12 if isinstance(obj, Promise):
15 if isinstance(obj, datetime):
16 return datetime.ctime(obj) + " " + (datetime.tzname(obj) or 'GMT')
18 return json.JSONEncoder.default(self, obj)
21 # shortcut for JSON reponses
22 class JSONResponse(http.HttpResponse):
24 def __init__(self, data={}, **kwargs):
26 kwargs.pop('mimetype', None)
28 data = json.dumps(data, cls=ExtendedEncoder)
29 super(JSONResponse, self).__init__(data, mimetype="application/json", **kwargs)
33 class JSONFormInvalid(JSONResponse):
34 def __init__(self, form):
35 super(JSONFormInvalid, self).__init__(form.errors, status=400)
38 class JSONServerError(JSONResponse):
39 def __init__(self, *args, **kwargs):
40 kwargs['status'] = 500
41 super(JSONServerError, self).__init__(*args, **kwargs)
44 def ajax_login_required(view):
46 def authenticated_view(request, *args, **kwargs):
47 if not request.user.is_authenticated():
48 return http.HttpResponse("Login required.", status=401, mimetype="text/plain")
49 return view(request, *args, **kwargs)
50 return authenticated_view
53 def ajax_require_permission(permission):
56 def authorized_view(request, *args, **kwargs):
57 if not request.user.has_perm(permission):
58 return http.HttpResponse("Access Forbidden.", status=403, mimetype="text/plain")
59 return view(request, *args, **kwargs)
60 return authorized_view
65 def recursive_groupby(iterable):
67 # >>> recursive_groupby([1,2,3,4,5])
70 >>> recursive_groupby([[1]])
73 >>> recursive_groupby([('a', 1),('a', 2), 3, ('b', 4), 5])
74 ['a', [1, 2], 3, 'b', [4], 5]
76 >>> recursive_groupby([('a', 'x', 1),('a', 'x', 2), ('a', 'x', 3)])
77 ['a', ['x', [1, 2, 3]]]
81 def _generator(iterator):
86 if not isinstance(item, collections.Sequence):
87 if grouper is not None:
90 yield recursive_groupby(group)
96 if grouper is not None:
99 yield recursive_groupby(group)
112 if grouper != item[0]:
113 if grouper is not None:
116 yield recursive_groupby(group)
123 group.append(item[1:])
125 if grouper is not None:
128 yield recursive_groupby(group)
132 return list(_generator(iterable))
137 View decorator, which puts tab info on a request.
141 def wrapped(request, *args, **kwargs):
142 request.wiki_active_tab = tab
143 return f(request, *args, **kwargs)
148 class ChunksList(object):
149 def __init__(self, chunk_qs):
150 self.chunk_qs = chunk_qs.annotate(
151 book_length=Count('book__chunk')).select_related(
152 'book', 'stage__name',
155 self.book_ids = [x['book_id'] for x in chunk_qs.values('book_id')]
157 def __getitem__(self, key):
158 if isinstance(key, slice):
159 return self.get_slice(key)
160 elif isinstance(key, int):
161 return self.get_slice(slice(key, key+1))[0]
163 raise TypeError('Unsupported list index. Must be a slice or an int.')
166 return len(self.book_ids)
168 def get_slice(self, slice_):
169 book_ids = self.book_ids[slice_]
170 chunk_qs = self.chunk_qs.filter(book__in=book_ids)
174 for chunk in chunk_qs:
175 if chunk.book != book:
177 chunks_list.append(ChoiceChunks(book, [chunk], chunk.book_length))
179 chunks_list[-1].chunks.append(chunk)
183 class ChoiceChunks(object):
185 Associates the given chunks iterable for a book.
190 def __init__(self, book, chunks, book_length):
193 self.book_length = book_length