from django.shortcuts import render from django.utils.decorators import method_decorator from django.views.generic import FormView from django.views.generic.detail import SingleObjectMixin from judge.utils.diggpaginator import DiggPaginator from django.utils.html import mark_safe def class_view_decorator(function_decorator): """Convert a function based decorator into a class based decorator usable on class based Views. Can't subclass the `View` as it breaks inheritance (super in particular), so we monkey-patch instead. """ def simple_decorator(View): View.dispatch = method_decorator(function_decorator)(View.dispatch) return View return simple_decorator def generic_message(request, title, message, status=None): return render( request, "generic-message.html", { "message": message, "title": title, }, status=status, ) def paginate_query_context(request): query = request.GET.copy() query.setlist("page", []) query = query.urlencode() if query: return { "page_prefix": "%s?%s&page=" % (request.path, query), "first_page_href": "%s?%s" % (request.path, query), } else: return { "page_prefix": "%s?page=" % request.path, "first_page_href": request.path, } class TitleMixin(object): title = "(untitled)" content_title = None def get_context_data(self, **kwargs): context = super(TitleMixin, self).get_context_data(**kwargs) context["title"] = self.get_title() content_title = self.get_content_title() if content_title is not None: context["content_title"] = content_title return context def get_content_title(self): return self.content_title def get_title(self): return self.title class DiggPaginatorMixin(object): def get_paginator( self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs ): return DiggPaginator( queryset, per_page, body=6, padding=2, orphans=orphans, allow_empty_first_page=allow_empty_first_page, **kwargs ) class QueryStringSortMixin(object): all_sorts = None default_sort = None default_desc = () def get_default_sort_order(self, request): return self.default_sort def get(self, request, *args, **kwargs): order = request.GET.get("order", "") if not ( (not order.startswith("-") or order.count("-") == 1) and (order.lstrip("-") in self.all_sorts) ): order = self.get_default_sort_order(request) self.order = order return super(QueryStringSortMixin, self).get(request, *args, **kwargs) def get_sort_context(self): query = self.request.GET.copy() query.setlist("order", []) query = query.urlencode() sort_prefix = ( "%s?%s&order=" % (self.request.path, query) if query else "%s?order=" % self.request.path ) current = self.order.lstrip("-") links = { key: sort_prefix + ("-" if key in self.default_desc else "") + key for key in self.all_sorts } links[current] = ( sort_prefix + ("" if self.order.startswith("-") else "-") + current ) order = {key: "" for key in self.all_sorts} order[current] = " \u25BE" if self.order.startswith("-") else " \u25B4" return {"sort_links": links, "sort_order": order} def get_sort_paginate_context(self): return paginate_query_context(self.request) def short_circuit_middleware(view): view.short_circuit_middleware = True return view class SingleObjectFormView(SingleObjectMixin, FormView): def post(self, request, *args, **kwargs): self.object = self.get_object() return super().post(request, *args, **kwargs) def get(self, request, *args, **kwargs): self.object = self.get_object() return super().get(request, *args, **kwargs)