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, param="date"): date = self.request.GET.get(param) return str_to_date(date, "-") if date else self.kwargs[param] if param 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("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, **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 dispatch(self, request, *args, **kwargs): self.parent = self.get_parent(request, **kwargs) return super().dispatch(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): parent = kwargs.setdefault("parent", self.parent) if parent is not None and parent.cover: kwargs.setdefault("cover", parent.cover.url) 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) class VueFormDataMixin: """Provide form information as data to be used with vue components.""" # Note: values corresponds to AFormSet expected one def get_form_items(self, formset): return [form.initial for form in formset.forms] def get_form_field_data(self, form, values=None): """Return form fields as data.""" model = form.Meta.model fields = ((name, field, model._meta.get_field(name)) for name, field in form.base_fields.items()) return [ { "name": name, "label": str(m_field.verbose_name).capitalize(), "help": str(m_field.help_text).capitalize(), "hidden": field.widget.is_hidden, "value": values and values.get(name), } for name, field, m_field in fields ] def get_formset_data(self, formset, field_values=None, **kwargs): """Return formset as data object.""" return { "prefix": formset.prefix, "management": { "initial_forms": formset.initial_form_count(), "min_num_forms": formset.min_num, "max_num_forms": formset.max_num, }, "fields": self.get_form_field_data(formset.form, field_values), "initial_extra": formset.initial_extra and formset.initial_extra[0], "initials": self.get_form_items(formset), **kwargs, }