+
+
+def ajax_login_required(view):
+ @wraps(view)
+ def authenticated_view(request, *args, **kwargs):
+ if not request.user.is_authenticated():
+ return http.HttpResponse("Login required.", status=401, mimetype="text/plain")
+ return view(request, *args, **kwargs)
+ return authenticated_view
+
+
+def ajax_require_permission(permission):
+ def decorator(view):
+ @wraps(view)
+ def authorized_view(request, *args, **kwargs):
+ if not request.user.has_perm(permission):
+ return http.HttpResponse("Access Forbidden.", status=403, mimetype="text/plain")
+ return view(request, *args, **kwargs)
+ return authorized_view
+ return decorator
+
+import collections
+
+def recursive_groupby(iterable):
+ """
+# >>> recursive_groupby([1,2,3,4,5])
+# [1, 2, 3, 4, 5]
+
+ >>> recursive_groupby([[1]])
+ [1]