from django.shortcuts import get_object_or_404, redirect from ..models import StaticPage from ..utils import str_to_date __all__ = ["GetDateMixin", "ParentMixin", "AttachedToMixin"] class GetDateMixin: """Mixin offering utils to get date by `request.GET` or `kwargs['date']`""" date = None redirect_date_url = None def get_date(self): date = self.request.GET.get("date") return str_to_date(date, "-") if date is not None else self.kwargs["date"] if "date" in self.kwargs else None def get(self, *args, **kwargs): if self.redirect_date_url and self.request.GET.get("date"): return redirect( self.redirect_date_url, date=self.request.GET["date"].replace("-", "/"), ) self.date = self.get_date() return super().get(*args, **kwargs) class ParentMixin: """Optional parent page for a list view. Parent is fetched and passed to the template context when `parent_model` is provided (queryset is filtered by parent page in such case). """ parent_model = None """Parent model.""" parent_url_kwarg = "parent_slug" """Url lookup argument.""" parent_field = "slug" """Parent field for url lookup.""" parent = None """Parent page object.""" def get_parent(self, request, *args, **kwargs): if self.parent_model is None or self.parent_url_kwarg not in kwargs: return lookup = {self.parent_field: kwargs[self.parent_url_kwarg]} return get_object_or_404(self.parent_model.objects.select_related("cover"), **lookup) def get(self, request, *args, **kwargs): self.parent = self.get_parent(request, *args, **kwargs) return super().get(request, *args, **kwargs) def get_queryset(self): if self.parent is not None: return super().get_queryset().filter(parent=self.parent) return super().get_queryset() def get_context_data(self, **kwargs): self.parent = kwargs.setdefault("parent", self.parent) if self.parent is not None: kwargs.setdefault("cover", self.parent.cover) return super().get_context_data(**kwargs) class AttachedToMixin: """Mixin for views that can have a static page attached to it.""" attach_to_value = None """Value of StaticPage.attach_to.""" def get_page(self): if self.attach_to_value is not None: return StaticPage.objects.filter(attach_to=self.attach_to_value).published().first() return super().get_page() # FIXME: django-filter provides filter mixin, but I don't remember why this is # used. class FiltersMixin: """Mixin integrating Django filters' filter set.""" filterset = None filterset_class = None def get_filterset(self, data, query): return self.filterset_class(data, query) def get_queryset(self): query = super().get_queryset() if self.filterset_class: self.filterset = self.get_filterset(self.request.GET.copy(), query) return self.filterset.qs return query def get_context_data(self, **kwargs): filterset = kwargs.setdefault("filterset", self.filterset) if filterset.is_valid(): kwargs["filterset_data"] = filterset.form.cleaned_data else: kwargs["filterset_data"] = {} params = self.request.GET.copy() kwargs["get_params"] = params.pop("page", True) and params return super().get_context_data(**kwargs)