forked from rc/aircox
233 lines
7.2 KiB
Python
233 lines
7.2 KiB
Python
from django.http import HttpResponse
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.views.generic import DetailView, ListView
|
|
from django.views.generic.edit import CreateView, UpdateView
|
|
from django.urls import reverse
|
|
from honeypot.decorators import check_honeypot
|
|
|
|
from aircox.conf import settings
|
|
from ..filters import PageFilters
|
|
from ..forms import CommentForm
|
|
from ..models import Comment, Category
|
|
from .base import BaseView
|
|
from .mixins import AttachedToMixin, FiltersMixin, ParentMixin
|
|
|
|
__all__ = [
|
|
"attached_views",
|
|
"attach",
|
|
"BasePageListView",
|
|
"BasePageDetailView",
|
|
"PageDetailView",
|
|
"PageListView",
|
|
"PageUpdateView",
|
|
]
|
|
|
|
|
|
attached_views = {}
|
|
"""Register views by StaticPage.Target."""
|
|
|
|
|
|
def attach(cls):
|
|
"""Add decorated view class to `attached_views`"""
|
|
attached_views[cls.attach_to_value] = cls
|
|
return cls
|
|
|
|
|
|
class CanEditMixin:
|
|
"""Add context 'can_edit' set to True when object is editable by user."""
|
|
|
|
def can_edit(self, object):
|
|
"""Return True if user can edit current page."""
|
|
return False
|
|
|
|
def get_context_data(self, **kwargs):
|
|
return super().get_context_data(can_edit=self.can_edit(self.object), **kwargs)
|
|
|
|
|
|
class BasePageMixin:
|
|
category = None
|
|
|
|
def get_queryset(self):
|
|
qs = super().get_queryset().select_subclasses().select_related("cover")
|
|
if self.request.user.is_authenticated:
|
|
return qs
|
|
return qs.published()
|
|
|
|
def get_category(self, page, **kwargs):
|
|
if page:
|
|
if getattr(page, "category_id", None):
|
|
return page.category
|
|
if getattr(page, "parent_id", None):
|
|
return self.get_category(page.parent_subclass)
|
|
if slug := self.kwargs.get("category_slug"):
|
|
return Category.objects.get(slug=slug)
|
|
return None
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
kwargs.setdefault("category", self.category)
|
|
return super().get_context_data(*args, **kwargs)
|
|
|
|
|
|
class BasePageListView(AttachedToMixin, BasePageMixin, ParentMixin, BaseView, ListView):
|
|
"""Base view class for BasePage list."""
|
|
|
|
template_name = "aircox/basepage_list.html"
|
|
|
|
paginate_by = 30
|
|
has_headline = True
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
def get(self, *args, **kwargs):
|
|
self.category = self.get_category(self.parent)
|
|
return super().get(*args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
query = super().get_queryset()
|
|
if self.category:
|
|
query = query.filter(category=self.category)
|
|
return query
|
|
|
|
def get_context_data(self, **kwargs):
|
|
kwargs.setdefault("has_headline", self.has_headline)
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
parent = context.get("parent")
|
|
if not context.get("page"):
|
|
if not context.get("title"):
|
|
model = self.model._meta.verbose_name_plural
|
|
title = _("{model}")
|
|
context["title"] = title.format(model=model, parent=parent)
|
|
|
|
if not context.get("cover") and parent and parent.cover:
|
|
context["cover"] = parent.cover.url
|
|
|
|
return context
|
|
|
|
|
|
class BasePageDetailView(BasePageMixin, BaseView, DetailView):
|
|
"""Base view class for BasePage."""
|
|
|
|
template_name = "aircox/public.html"
|
|
context_object_name = "page"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
if self.object.cover:
|
|
kwargs.setdefault("cover", self.object.cover.url)
|
|
if self.object.title:
|
|
kwargs.setdefault("title", self.object.display_title)
|
|
return super().get_context_data(**kwargs)
|
|
|
|
def get_object(self):
|
|
if getattr(self, "object", None):
|
|
return self.object
|
|
|
|
obj = super().get_object()
|
|
self.category = self.get_category(obj)
|
|
return obj
|
|
|
|
def get_page(self):
|
|
return self.object
|
|
|
|
|
|
class PageListView(FiltersMixin, BasePageListView):
|
|
"""Page list view."""
|
|
|
|
filterset_class = PageFilters
|
|
template_name = None
|
|
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")
|
|
cat_ids = self.model.objects.published().values_list("category_id", flat=True)
|
|
self.categories = Category.objects.filter(id__in=cat_ids)
|
|
return qs
|
|
|
|
@classmethod
|
|
def get_secondary_nav(cls):
|
|
cat_ids = cls.model.objects.published().values_list("category_id", flat=True)
|
|
categories = Category.objects.filter(id__in=cat_ids)
|
|
return tuple(
|
|
(category.title, reverse(cls.model.list_url_name, kwargs={"category_slug": category.slug}))
|
|
for category in categories
|
|
)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
kwargs["categories"] = self.categories
|
|
return super().get_context_data(**kwargs)
|
|
|
|
|
|
class PageDetailView(CanEditMixin, BasePageDetailView):
|
|
"""Base view class for pages."""
|
|
|
|
template_name = None
|
|
context_object_name = "page"
|
|
|
|
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 "comment_form" not in kwargs:
|
|
kwargs["comment_form"] = self.get_comment_form()
|
|
kwargs["comments"] = Comment.objects.filter(page=self.object).order_by("-date")
|
|
|
|
if parent_subclass := getattr(self.object, "parent_subclass", None):
|
|
kwargs["parent"] = parent_subclass
|
|
|
|
if "related_objects" not in kwargs:
|
|
related = self.get_related_queryset()
|
|
if related:
|
|
related = related[: self.related_count]
|
|
kwargs["related_objects"] = related
|
|
return super().get_context_data(**kwargs)
|
|
|
|
def get_comment_form(self):
|
|
if settings.ALLOW_COMMENTS and self.object.allow_comments:
|
|
return CommentForm()
|
|
return None
|
|
|
|
@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)
|
|
|
|
|
|
class PageCreateView(CanEditMixin, BaseView, CreateView):
|
|
def get_page(self):
|
|
return self.object
|
|
|
|
def get_success_url(self):
|
|
return self.request.path
|
|
|
|
|
|
class PageUpdateView(CanEditMixin, BaseView, UpdateView):
|
|
def get_page(self):
|
|
return self.object
|
|
|
|
def get_success_url(self):
|
|
return self.request.path
|