From ae4be0e58c81d9acbadd6f5767db0e63f0ede6d6 Mon Sep 17 00:00:00 2001 From: Erik Stein Date: Wed, 27 Apr 2022 00:22:43 +0200 Subject: [PATCH] Page titles refactoring. --- shared/utils/models/pages.py | 99 ++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/shared/utils/models/pages.py b/shared/utils/models/pages.py index 83e9b0f..7a4ef4f 100644 --- a/shared/utils/models/pages.py +++ b/shared/utils/models/pages.py @@ -1,7 +1,7 @@ from django.conf import settings from django.db import models from django.utils.html import strip_tags -from django.utils.text import normalize_newlines +from django.utils.text import normalize_newlines, Truncator from django.utils.translation import gettext_lazy as _ from shared.multilingual.utils import i18n_fields_list @@ -18,98 +18,99 @@ if USE_TRANSLATABLE_FIELDS: TranslatableCharField, TranslatableTextField ) - # TODO populate_from might use settings.LANGUAGE_CODE - SLUG_POPULATE_FORM = getattr(settings, 'SLUG_POPULATE_FORM', 'name_en') + # TODO populate_from should use settings.LANGUAGE_CODE + # FIXME Wrong spelling! + SLUG_POPULATE_FROM = getattr(settings, 'SLUG_POPULATE_FROM', 'name_en') else: TranslatableCharField = models.CharField TranslatableTextField = models.TextField - SLUG_POPULATE_FORM = 'name' + SLUG_POPULATE_FROM = 'name' # TODO Make slimdown optional through settings # TODO Leave window_title alone, do not slimdown -class PageTitlesFunctionMixin(object): +class PageTitlesBehaviour: + """ + Implements fallback behaviour. + """ + def __str__(self): - return strip_tags(self.get_short_title()) + return strip_tags(slimdown(self.get_short_name())) def get_title(self): - return slimdown(firstof( - self.title, - self.get_short_title(), - '' - )) + return self.get_first_title_line() or \ + self.name def get_short_name(self): - return slimdown(self.short_name or self.name) - - # TODO Deprecated - get_short_title = get_short_name - - def get_window_title(self): - return strip_tags(slimdown( - firstof( - getattr(self, 'window_title', None), - self.get_short_title(), - self.get_first_title_line(), - '' - ) - )) + return getattr(self, 'short_name', '') or \ + Truncator(self.name).words(5, truncate="...") def get_first_title_line(self): """ - First line of title field. + First line of title field or self.name.. """ - return slimdown( - normalize_newlines(self.get_title()).partition("\n")[0] - ) + return normalize_newlines(getattr(self, 'long_title', '') or '').partition("\n")[0] def get_subtitle_lines(self): """ All but first line of the long title field. """ - return slimdown( - normalize_newlines(self.title).partition("\n")[2] + return normalize_newlines(getattr(self, 'long_title', '') or '').partition("\n")[2] + + def get_window_title(self): + return firstof( + getattr(self, 'window_title', None), + strip_tags(slimdown(self.get_short_name())), + strip_tags(slimdown(self.get_first_title_line())), ) -class PageTitlesMixin(PageTitlesFunctionMixin, models.Model): +PageTitlesFunctionMixin = PageTitlesBehaviour + + +class PageTitlesMixin(PageTitlesBehaviour, models.Model): """ - A model mixin containg title and slug field for models serving as website - pages with an URL. + A model mixin containg title and slug fields for models serving + as web pages with an URL. + + name: Main naming field, all other fields besides `slug` + are optional. + short_name: For menus etc. + long_title: Long title, composed of title line (first line) and + subtitle (all other lines) + window_title: Browser window title, also for search engine's results + slug: URL name + """ name = TranslatableCharField(_("Name"), max_length=250) + sort_name = TranslatableCharField(_("Short Name"), + max_length=250, null=True, blank=True, + help_text=_("Optional, used for sorting.")) short_name = TranslatableCharField(_("Short Name"), max_length=25, null=True, blank=True, help_text=_("Optional, used for menus etc.")) - title = TranslatableTextField(_("title/subtitle"), - null=True, blank=True, max_length=500) + long_title = TranslatableTextField(_("title/subtitle"), + null=True, blank=True, max_length=500, + help_text=_("Optional, long title for page content region. FIrst line is the title, other lines are the subtitle. Simplified Markdown.")) window_title = TranslatableCharField(_("window title"), null=True, blank=True, max_length=300) slug = DowngradingSlugField(_("URL-Name"), max_length=200, - populate_from=SLUG_POPULATE_FORM, unique_slug=True, blank=True) + populate_from=SLUG_POPULATE_FROM, unique_slug=True, blank=True) class Meta: abstract = True - - # FIXME short_title is deprecated - @property - def short_title(self): - return self.get_short_title() - - @short_title.setter - def short_title(self, value): - self.name = value + ordering = ['sort_name', 'name'] -class PageTitleAdminMixin(object): +class PageTitlesAdminMixin: list_display = ['name', 'slug'] - search_fields = ['name', 'title', 'window_title'] + search_fields = ['name', 'short_name', 'long_title', 'window_title'] if USE_TRANSLATABLE_FIELDS: search_fields = i18n_fields_list(search_fields) prepopulated_fields = { - 'slug': [SLUG_POPULATE_FORM] + 'slug': [SLUG_POPULATE_FROM] }