From 40920b01eef6a28a975a2468b51b14b9593e124b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Wersd=C3=B6rfer?= Date: Sat, 2 Sep 2023 00:38:45 +0200 Subject: [PATCH] #105 select theme view + tests and some refactoring --- cast/forms.py | 16 ++++- cast/models/__init__.py | 11 ++- cast/models/index_pages.py | 29 ++++---- cast/models/theme.py | 12 ++++ .../cast/plain/blog_list_of_posts.html | 2 + cast/templates/cast/plain/select_theme.html | 5 ++ cast/urls.py | 3 + cast/views/__init__.py | 5 ++ cast/views/theme.py | 43 +++++++++++ tests/theme_test.py | 72 +++++++++++++++++++ 10 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 cast/templates/cast/plain/select_theme.html create mode 100644 cast/views/theme.py diff --git a/cast/forms.py b/cast/forms.py index ebb956ed..a6ceaebc 100644 --- a/cast/forms.py +++ b/cast/forms.py @@ -11,7 +11,7 @@ from wagtail.admin.forms.search import SearchForm from wagtail.models import Collection -from .models import Audio, ChapterMark, Video +from .models import Audio, ChapterMark, Video, get_template_base_dir_choices class VideoForm(forms.ModelForm): @@ -183,3 +183,17 @@ def clean_q(self) -> str: if not query: raise forms.ValidationError(_("Please enter a search term")) return query + + +class SelectThemeForm(forms.Form): + template_base_dir = forms.ChoiceField( + choices=[], + label=_("Theme"), + help_text=_("Select a theme for this site."), + required=True, + ) + next = forms.CharField(widget=forms.HiddenInput, required=False) + + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.fields["template_base_dir"].choices = get_template_base_dir_choices() diff --git a/cast/models/__init__.py b/cast/models/__init__.py index a0c3b4a4..4cbc87d4 100644 --- a/cast/models/__init__.py +++ b/cast/models/__init__.py @@ -1,12 +1,16 @@ from .audio import Audio, ChapterMark, sync_chapter_marks from .file import File from .gallery import Gallery, get_or_create_gallery -from .index_pages import Blog, Podcast +from .index_pages import Blog, HtmxHttpRequest, Podcast from .itunes import ItunesArtWork from .moderation import SpamFilter from .pages import Episode, HomePage, Post, sync_media_ids from .snippets import PostCategory -from .theme import TemplateBaseDirectory +from .theme import ( + TemplateBaseDirectory, + get_template_base_dir, + get_template_base_dir_choices, +) from .video import Video, get_video_dimensions __all__ = [ @@ -17,7 +21,10 @@ "File", "Gallery", "get_or_create_gallery", + "get_template_base_dir", + "get_template_base_dir_choices", "HomePage", + "HtmxHttpRequest", "ItunesArtWork", "Post", "PostCategory", diff --git a/cast/models/index_pages.py b/cast/models/index_pages.py index 16cb0ecb..51ca610e 100644 --- a/cast/models/index_pages.py +++ b/cast/models/index_pages.py @@ -4,13 +4,13 @@ from datetime import datetime from typing import Any +import django.forms.forms from django.core.paginator import InvalidPage, Paginator from django.db import models from django.http import Http404, HttpRequest from django.http.request import QueryDict from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from django_htmx.middleware import HtmxDetails from wagtail.admin.panels import FieldPanel from wagtail.api import APIField from wagtail.fields import RichTextField @@ -20,8 +20,9 @@ from cast.filters import PostFilterset from cast.models.itunes import ItunesArtWork +from ..views import HtmxHttpRequest from .pages import Post -from .theme import TemplateBaseDirectory, get_template_base_dir_choices +from .theme import get_template_base_dir, get_template_base_dir_choices logger = logging.getLogger(__name__) @@ -29,10 +30,6 @@ ContextDict = dict[str, Any] -class HtmxHttpRequest(HttpRequest): - htmx: HtmxDetails - - class Blog(Page): """ This is the index page for a blog. It contains a list of posts. @@ -92,13 +89,8 @@ class Blog(Page): def __str__(self): return self.title - def get_template_base_dir(self, request: HttpRequest) -> str: - if hasattr(request, "session") and (template_base_dir := request.session.get("template_base_dir")) is not None: - return template_base_dir - if self.template_base_dir is not None: - return self.template_base_dir - else: - return TemplateBaseDirectory.for_request(request).name + def get_template_base_dir(self, request: HtmxHttpRequest) -> str: + return get_template_base_dir(request, self.template_base_dir) def get_template(self, request: HtmxHttpRequest, *args, **kwargs) -> str: template_base_dir = self.get_template_base_dir(request) @@ -200,6 +192,16 @@ def comment_post_url(self) -> str: def pagination_page_size(self) -> int: return appsettings.POST_LIST_PAGINATION + def get_theme_form(self, request: HttpRequest) -> django.forms.forms.Form: + from ..forms import SelectThemeForm + + return SelectThemeForm( + initial={ + "template_base_dir": self.get_template_base_dir(request), + "next": request.path, + } + ) + def get_context(self, request: HttpRequest, *args, **kwargs) -> ContextDict: context = super().get_context(request, *args, **kwargs) get_params = request.GET.copy() @@ -209,6 +211,7 @@ def get_context(self, request: HttpRequest, *args, **kwargs) -> ContextDict: context["posts"] = context["object_list"] # convenience context["blog"] = self context["use_audio_player"] = any([post.has_audio for post in context["posts"]]) + context["theme_form"] = self.get_theme_form(request) return context diff --git a/cast/models/theme.py b/cast/models/theme.py index 3396e67b..29dbb480 100644 --- a/cast/models/theme.py +++ b/cast/models/theme.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import Union from django.conf import settings from django.db import models @@ -7,6 +8,8 @@ from django.utils.translation import gettext_lazy as _ from wagtail.contrib.settings.models import BaseSiteSetting, register_setting +from ..views import HtmxHttpRequest + def get_required_template_names() -> list[str]: """ @@ -106,6 +109,15 @@ def get_template_base_dir_choices() -> list[tuple[str, str]]: return choices +def get_template_base_dir(request: HtmxHttpRequest, pre_selected: Union[str, None]) -> str: + if hasattr(request, "session") and (template_base_dir := request.session.get("template_base_dir")) is not None: + return template_base_dir + if pre_selected is not None: + return pre_selected + else: + return TemplateBaseDirectory.for_request(request).name + + @register_setting class TemplateBaseDirectory(BaseSiteSetting): """ diff --git a/cast/templates/cast/plain/blog_list_of_posts.html b/cast/templates/cast/plain/blog_list_of_posts.html index 4adc51bb..a6fdf549 100644 --- a/cast/templates/cast/plain/blog_list_of_posts.html +++ b/cast/templates/cast/plain/blog_list_of_posts.html @@ -36,6 +36,8 @@

Feed

{% block navigation %}