from django.http import Http404, HttpResponse from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, ListView from honeypot.decorators import check_honeypot from ..filters import PageFilters from ..forms import CommentForm from ..models import Comment from ..utils import Redirect from .base import BaseView from .mixins import AttachedToMixin, FiltersMixin, ParentMixin __all__ = [ "BasePageListView", "BasePageDetailView", "PageDetailView", "PageListView", ] class BasePageListView(AttachedToMixin, ParentMixin, BaseView, ListView): """Base view class for BasePage list.""" template_name = "aircox/basepage_list.html" item_template_name = "aircox/widgets/page_item.html" has_sidebar = True paginate_by = 30 has_headline = True def get(self, *args, **kwargs): return super().get(*args, **kwargs) def get_queryset(self): return ( super() .get_queryset() .select_subclasses() .published() .select_related("cover") ) def get_context_data(self, **kwargs): kwargs.setdefault("item_template_name", self.item_template_name) kwargs.setdefault("has_headline", self.has_headline) return super().get_context_data(**kwargs) class BasePageDetailView(BaseView, DetailView): """Base view class for BasePage.""" template_name = "aircox/basepage_detail.html" context_object_name = "page" has_filters = False def get_queryset(self): return super().get_queryset().select_related("cover") # This should not exists: it allows mapping not published pages # or it should be only used for trashed pages. def not_published_redirect(self, page): """When a page is not published, redirect to the returned url instead of an HTTP 404 code.""" return None def get_object(self): if getattr(self, "object", None): return self.object obj = super().get_object() if not obj.is_published: redirect_url = self.not_published_redirect(obj) if redirect_url: raise Redirect(redirect_url) raise Http404("%s not found" % self.model._meta.verbose_name) return obj def get_page(self): return self.object class PageListView(FiltersMixin, BasePageListView): """Page list view.""" filterset_class = PageFilters template_name = None has_filters = True categories = None filters = None def get_template_names(self): return super().get_template_names() + ["aircox/page_list.html"] def get_filterset(self, data, query): # FIXME: not the most efficient, cause join then split (django filters) data["category__id__in"] = ",".join(data.getlist("category__id__in")) return super().get_filterset(data, query) def get_queryset(self): qs = ( super() .get_queryset() .select_related("category") .order_by("-pub_date") ) return qs def get_context_data(self, **kwargs): kwargs["categories"] = ( self.model.objects.published() .filter(category__isnull=False) .values_list("category__title", "category__id") .distinct() ) return super().get_context_data(**kwargs) class PageDetailView(BasePageDetailView): """Base view class for pages.""" template_name = None context_object_name = "page" has_filters = False def get_template_names(self): return super().get_template_names() + ["aircox/page_detail.html"] def get_queryset(self): return super().get_queryset().select_related("category") def get_context_data(self, **kwargs): if self.object.allow_comments and "comment_form" not in kwargs: kwargs["comment_form"] = CommentForm() kwargs["comments"] = Comment.objects.filter(page=self.object).order_by( "-date" ) return super().get_context_data(**kwargs) @classmethod def as_view(cls, *args, **kwargs): view = super(PageDetailView, cls).as_view(*args, **kwargs) return check_honeypot(view, field_name="website") def post(self, request, *args, **kwargs): self.object = self.get_object() if not self.object.allow_comments: return HttpResponse(_("comments are not allowed"), status=503) form = CommentForm(request.POST) comment = form.save(commit=False) comment.page = self.object comment.save() return self.get(request, *args, **kwargs)