|
|
|
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]
|
|
|
|
}
|