aircox/aircox/views/mixins.py
Thomas Kairos 2ce435fb5d !112 !94: tests commons modules that contains most of the logic + zoneinfo (#113)
!112

Co-authored-by: bkfox <thomas bkfox net>
Reviewed-on: #113
2023-08-23 15:28:17 +02:00

122 lines
3.6 KiB
Python

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)