2020-01-02 18:32:15 +00:00
|
|
|
'''CMS Models'''
|
|
|
|
|
2019-12-31 12:05:12 +00:00
|
|
|
import swapper
|
2020-01-02 18:32:15 +00:00
|
|
|
|
2019-03-27 15:49:14 +00:00
|
|
|
from django.db import models
|
|
|
|
from django.urls import reverse
|
|
|
|
from django.conf import settings
|
2020-01-02 00:56:15 +00:00
|
|
|
from django.forms import TextInput, Select
|
2019-03-27 15:49:14 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from embed_video.fields import EmbedVideoField
|
2019-12-31 12:05:12 +00:00
|
|
|
from polymorphic.models import PolymorphicModel
|
2020-01-02 22:37:26 +00:00
|
|
|
from markdownfield.models import MarkdownField, RenderedMarkdownField
|
|
|
|
from markdownfield.validators import VALIDATOR_NULL
|
2019-04-02 13:07:36 +00:00
|
|
|
|
2019-11-22 10:57:10 +00:00
|
|
|
from numberedmodel.models import NumberedModel
|
|
|
|
|
2019-08-23 15:19:40 +00:00
|
|
|
class VarCharField(models.TextField):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Variable width CharField'''
|
2019-08-23 15:19:40 +00:00
|
|
|
def formfield(self, **kwargs):
|
|
|
|
kwargs.update({'widget': TextInput})
|
|
|
|
return super().formfield(**kwargs)
|
|
|
|
|
2020-01-02 00:56:15 +00:00
|
|
|
class VarCharChoiceField(models.TextField):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Variable width CharField with choices'''
|
2020-01-02 00:56:15 +00:00
|
|
|
def formfield(self, **kwargs):
|
|
|
|
kwargs.update({'widget': Select})
|
|
|
|
return super().formfield(**kwargs)
|
|
|
|
|
|
|
|
class BasePage(NumberedModel):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Abstract base model for pages'''
|
2019-03-27 15:49:14 +00:00
|
|
|
slug = models.SlugField(_('slug'), help_text=_('A short identifier to use in URLs'), blank=True, unique=True)
|
2020-01-02 22:37:26 +00:00
|
|
|
title = VarCharField(_('title'))
|
|
|
|
position = models.PositiveIntegerField(_('position'), blank=True)
|
2019-03-27 15:49:14 +00:00
|
|
|
menu = models.BooleanField(_('visible in menu'), default=True)
|
|
|
|
|
|
|
|
def __str__(self):
|
2019-08-26 07:47:52 +00:00
|
|
|
if not self.pk:
|
|
|
|
return str(_('New page'))
|
2020-01-02 18:32:15 +00:00
|
|
|
return self.title
|
2019-03-27 15:49:14 +00:00
|
|
|
|
|
|
|
def get_absolute_url(self):
|
|
|
|
if self.slug:
|
2020-01-02 00:56:15 +00:00
|
|
|
return reverse('cms:page', args=[self.slug])
|
2020-01-02 18:32:15 +00:00
|
|
|
return reverse('cms:page')
|
2019-03-27 15:49:14 +00:00
|
|
|
|
|
|
|
class Meta:
|
2020-01-02 00:56:15 +00:00
|
|
|
abstract = True
|
2019-03-27 15:49:14 +00:00
|
|
|
verbose_name = _('Page')
|
|
|
|
verbose_name_plural = _('Pages')
|
|
|
|
ordering = ['position']
|
|
|
|
|
2019-12-31 12:05:12 +00:00
|
|
|
class BaseSection(NumberedModel, PolymorphicModel):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Abstract base model for sections'''
|
2020-01-02 00:56:15 +00:00
|
|
|
TYPES = []
|
|
|
|
page = models.ForeignKey(swapper.get_model_name('cms', 'Page'), verbose_name=_('page'), related_name='sections', on_delete=models.PROTECT)
|
2020-01-02 22:37:26 +00:00
|
|
|
type = VarCharChoiceField(_('type'), default='', choices=TYPES)
|
2020-01-02 00:56:15 +00:00
|
|
|
title = VarCharField(_('title'), blank=True)
|
2020-01-02 22:37:26 +00:00
|
|
|
position = models.PositiveIntegerField(_('position'), blank=True)
|
2019-03-27 15:49:14 +00:00
|
|
|
color = models.PositiveIntegerField(_('color'), default=1, choices=settings.SECTION_COLORS)
|
2020-01-02 22:37:26 +00:00
|
|
|
content = MarkdownField(_('content'), rendered_field='content_rendered', validator=VALIDATOR_NULL, use_admin_editor=False, blank=True)
|
|
|
|
content_rendered = RenderedMarkdownField()
|
2019-03-27 15:49:14 +00:00
|
|
|
image = models.ImageField(_('image'), blank=True)
|
2019-04-24 20:18:07 +00:00
|
|
|
video = EmbedVideoField(_('video'), blank=True, help_text=_('Paste a YouTube, Vimeo, or SoundCloud link'))
|
2020-01-02 00:56:15 +00:00
|
|
|
button_text = VarCharField(_('button text'), blank=True)
|
|
|
|
button_link = VarCharField(_('button link'), blank=True)
|
2019-03-27 15:49:14 +00:00
|
|
|
|
|
|
|
def number_with_respect_to(self):
|
|
|
|
return self.page.sections.all()
|
|
|
|
|
|
|
|
def __str__(self):
|
2019-08-26 07:47:52 +00:00
|
|
|
if not self.pk:
|
|
|
|
return str(_('New section'))
|
|
|
|
elif not self.title:
|
|
|
|
return str(_('Untitled'))
|
|
|
|
else:
|
|
|
|
return self.title
|
2019-03-27 15:49:14 +00:00
|
|
|
|
|
|
|
class Meta:
|
2019-12-31 12:05:12 +00:00
|
|
|
abstract = True
|
2019-03-27 15:49:14 +00:00
|
|
|
verbose_name = _('section')
|
|
|
|
verbose_name_plural = _('sections')
|
|
|
|
ordering = ['position']
|
2020-01-02 00:56:15 +00:00
|
|
|
|
|
|
|
class Page(BasePage):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Swappable page model'''
|
2020-01-02 00:56:15 +00:00
|
|
|
class Meta(BasePage.Meta):
|
|
|
|
swappable = swapper.swappable_setting('cms', 'Page')
|
2019-03-27 15:49:14 +00:00
|
|
|
|
2019-12-31 12:05:12 +00:00
|
|
|
class Section(BaseSection):
|
2020-01-02 18:32:15 +00:00
|
|
|
'''Swappable section model'''
|
2020-01-02 00:56:15 +00:00
|
|
|
class Meta(BaseSection.Meta):
|
2019-12-31 12:05:12 +00:00
|
|
|
swappable = swapper.swappable_setting('cms', 'Section')
|