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