from django.conf import settings from django.db import models from django.utils.html import strip_tags from django.utils.text import normalize_newlines, Truncator from django.utils.translation import gettext_lazy as _ from shared.multilingual.utils import i18n_fields_list from ..functional import firstof from ..text import slimdown from .slugs import DowngradingSlugField from ..conf import USE_TRANSLATABLE_FIELDS if USE_TRANSLATABLE_FIELDS: from shared.multilingual.utils.fields import ( TranslatableCharField, TranslatableTextField ) # 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_FROM = 'name' # TODO Make slimdown optional through settings # TODO Leave window_title alone, do not slimdown class PageTitlesBehaviour: """ Implements fallback behaviour. """ def __str__(self): return strip_tags(slimdown(self.get_short_name())) def get_title(self): return self.get_first_title_line() or \ self.name def get_short_name(self): return getattr(self, 'short_name', '') or \ Truncator(self.name).words(5, truncate="...") def get_first_title_line(self): """ First line of title field or self.name.. """ 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 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())), ) PageTitlesFunctionMixin = PageTitlesBehaviour class PageTitlesMixin(PageTitlesBehaviour, models.Model): """ 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.")) 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_FROM, unique_slug=True, blank=True) class Meta: abstract = True ordering = ['sort_name', 'name'] class PageTitlesAdminMixin: list_display = ['name', 'slug'] 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_FROM] }