#132 | #121: backoffice / dev-1.0-121 (#131)

cfr #121

Co-authored-by: Christophe Siraut <d@tobald.eu.org>
Co-authored-by: bkfox <thomas bkfox net>
Co-authored-by: Thomas Kairos <thomas@bkfox.net>
Reviewed-on: rc/aircox#131
Co-authored-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
Co-committed-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
This commit is contained in:
2024-04-28 22:02:09 +02:00
committed by Thomas Kairos
parent 1e17a1334a
commit 55123c386d
348 changed files with 124397 additions and 17879 deletions

View File

@@ -1,72 +1,119 @@
from django.http import Http404, HttpResponse
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
from ..utils import Redirect
from ..models import Comment, Category
from .base import BaseView
from .mixins import AttachedToMixin, FiltersMixin, ParentMixin
__all__ = [
"attached_views",
"attach",
"BasePageListView",
"BasePageDetailView",
"PageDetailView",
"PageListView",
"PageUpdateView",
]
class BasePageListView(AttachedToMixin, ParentMixin, BaseView, ListView):
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 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"
item_template_name = "aircox/widgets/page_item.html"
has_sidebar = True
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):
return super().get_queryset().select_subclasses().published().select_related("cover")
query = super().get_queryset()
if self.category:
query = query.filter(category=self.category)
return query
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)
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(BaseView, DetailView):
class BasePageDetailView(BasePageMixin, BaseView, DetailView):
"""Base view class for BasePage."""
template_name = "aircox/basepage_detail.html"
template_name = "aircox/public.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_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()
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)
self.category = self.get_category(obj)
return obj
def get_page(self):
@@ -78,7 +125,6 @@ class PageListView(FiltersMixin, BasePageListView):
filterset_class = PageFilters
template_name = None
has_filters = True
categories = None
filters = None
@@ -92,15 +138,21 @@ class PageListView(FiltersMixin, BasePageListView):
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
def get_context_data(self, **kwargs):
kwargs["categories"] = (
self.model.objects.published()
.filter(category__isnull=False)
.values_list("category__title", "category__id")
.distinct()
@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)
@@ -109,7 +161,10 @@ class PageDetailView(BasePageDetailView):
template_name = None
context_object_name = "page"
has_filters = False
def can_edit(self, object):
"""Return True if user can edit current page."""
return False
def get_template_names(self):
return super().get_template_names() + ["aircox/page_detail.html"]
@@ -118,11 +173,26 @@ class PageDetailView(BasePageDetailView):
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()
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
kwargs["can_edit"] = self.can_edit(self.object)
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)
@@ -138,3 +208,19 @@ class PageDetailView(BasePageDetailView):
comment.page = self.object
comment.save()
return self.get(request, *args, **kwargs)
class PageCreateView(BaseView, CreateView):
def get_page(self):
return self.object
def get_success_url(self):
return self.request.path
class PageUpdateView(BaseView, UpdateView):
def get_page(self):
return self.object
def get_success_url(self):
return self.request.path