diff --git a/aircox/admin/__init__.py b/aircox/admin/__init__.py
index 21436bb..ce5dc4a 100644
--- a/aircox/admin/__init__.py
+++ b/aircox/admin/__init__.py
@@ -1,6 +1,7 @@
from .article import ArticleAdmin
from .episode import DiffusionAdmin, EpisodeAdmin
from .log import LogAdmin
+from .page import PageAdmin, StaticPageAdmin
from .program import ProgramAdmin, ScheduleAdmin, StreamAdmin
from .sound import SoundAdmin, TrackAdmin
from .station import StationAdmin
diff --git a/aircox/admin/article.py b/aircox/admin/article.py
index 4a08dc9..b6b8b03 100644
--- a/aircox/admin/article.py
+++ b/aircox/admin/article.py
@@ -11,8 +11,7 @@ __all__ = ['ArticleAdmin']
@admin.register(Article)
class ArticleAdmin(PageAdmin):
- list_filter = PageAdmin.list_filter
- search_fields = PageAdmin.search_fields + ['parent__title']
+ search_fields = PageAdmin.search_fields + ('parent__title',)
# TODO: readonly field
diff --git a/aircox/admin/episode.py b/aircox/admin/episode.py
index 81a6647..44ddf20 100644
--- a/aircox/admin/episode.py
+++ b/aircox/admin/episode.py
@@ -56,7 +56,7 @@ class EpisodeAdmin(PageAdmin):
form = EpisodeAdminForm
list_display = PageAdmin.list_display
list_filter = PageAdmin.list_filter
- search_fields = PageAdmin.search_fields + ['parent__title']
+ search_fields = PageAdmin.search_fields + ('parent__title',)
# readonly_fields = ('parent',)
inlines = [TracksInline, SoundInline, DiffusionInline]
diff --git a/aircox/admin/page.py b/aircox/admin/page.py
index 0a252e0..b0b0e50 100644
--- a/aircox/admin/page.py
+++ b/aircox/admin/page.py
@@ -1,4 +1,4 @@
-import urllib
+from copy import deepcopy
from django.contrib import admin
from django.http import QueryDict
@@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from adminsortable2.admin import SortableInlineAdminMixin
-from ..models import Category, NavItem, Page
+from ..models import Category, NavItem, Page, StaticPage
__all__ = ['CategoryAdmin', 'PageAdmin', 'NavItemInline']
@@ -22,25 +22,24 @@ class CategoryAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
-# limit category choice
-class PageAdmin(admin.ModelAdmin):
- list_display = ('cover_thumb', 'title', 'status', 'category', 'parent')
+class BasePageAdmin(admin.ModelAdmin):
+ list_display = ('cover_thumb', 'title', 'status', 'parent')
list_display_links = ('cover_thumb', 'title')
- list_editable = ('status', 'category')
- list_filter = ('status', 'category')
+ list_editable = ('status',)
+ list_filter = ('status',)
prepopulated_fields = {"slug": ("title",)}
# prepopulate fields using changelist's filters
prepopulated_filters = ('parent',)
- search_fields = ['title', 'category__title']
+ search_fields = ('title',)
fieldsets = [
('', {
- 'fields': ['title', 'slug', 'category', 'cover', 'content'],
+ 'fields': ['title', 'slug', 'cover', 'content'],
}),
(_('Publication Settings'), {
- 'fields': ['featured', 'allow_comments', 'status', 'parent'],
- 'classes': ('collapse',),
+ 'fields': ['status', 'parent'],
+ # 'classes': ('collapse',),
}),
]
@@ -59,10 +58,16 @@ class PageAdmin(admin.ModelAdmin):
def get_common_context(self, query, extra_context=None):
extra_context = extra_context or {}
parent = query.get('parent', None)
- if parent is not None:
- extra_context['parent'] = Page.objects.get_subclass(id=parent)
+ extra_context['parent'] = None if parent is None else \
+ Page.objects.get_subclass(id=parent)
+
return extra_context
+ def render_change_form(self, request, context, *args, **kwargs):
+ if context['original'] and not 'parent' in context:
+ context['parent'] = context['original'].parent
+ return super().render_change_form(request, context, *args, **kwargs)
+
def add_view(self, request, form_url='', extra_context=None):
filters = QueryDict(request.GET.get('_changelist_filters', ''))
extra_context = self.get_common_context(filters, extra_context)
@@ -73,6 +78,27 @@ class PageAdmin(admin.ModelAdmin):
return super().changelist_view(request, extra_context)
+class PageAdmin(BasePageAdmin):
+ list_display = BasePageAdmin.list_display + ('category',)
+ list_editable = BasePageAdmin.list_editable + ('category',)
+ list_filter = BasePageAdmin.list_editable + ('category',)
+ search_fields = ('category__title',)
+ fieldsets = deepcopy(BasePageAdmin.fieldsets)
+
+ fieldsets[0][1]['fields'].insert(fieldsets[0][1]['fields'].index('slug') + 1, 'category')
+ fieldsets[1][1]['fields'] += ('featured', 'allow_comments')
+
+
+@admin.register(StaticPage)
+class StaticPageAdmin(BasePageAdmin):
+ list_display = BasePageAdmin.list_display + ('view','menu_title')
+ list_editable = BasePageAdmin.list_editable + ('menu_title',)
+ fieldsets = deepcopy(BasePageAdmin.fieldsets)
+
+ fieldsets[0][1]['fields'].insert(fieldsets[0][1]['fields'].index('slug') + 1, 'menu_title')
+ fieldsets[1][1]['fields'] += ('view',)
+
+
class NavItemInline(SortableInlineAdminMixin, admin.TabularInline):
model = NavItem
diff --git a/aircox/models/__init__.py b/aircox/models/__init__.py
index a312fef..1e94504 100644
--- a/aircox/models/__init__.py
+++ b/aircox/models/__init__.py
@@ -1,5 +1,5 @@
from .article import Article
-from .page import Category, Page, Comment, NavItem
+from .page import Category, Page, StaticPage, Comment, NavItem
from .program import Program, Stream, Schedule
from .episode import Episode, Diffusion
from .log import Log
diff --git a/aircox/models/log.py b/aircox/models/log.py
index bb5c95a..dbde3c9 100644
--- a/aircox/models/log.py
+++ b/aircox/models/log.py
@@ -29,7 +29,7 @@ class LogQuerySet(models.QuerySet):
start = tz.datetime.combine(date, datetime.time())
end = tz.datetime.combine(date, datetime.time(23, 59, 59, 999))
return self.filter(date__range = (start, end))
- # this filter does not work with sql
+ # this filter does not work with mysql
# return self.filter(date__date=date)
def after(self, date):
diff --git a/aircox/models/page.py b/aircox/models/page.py
index a4e2e0a..abc5cf4 100644
--- a/aircox/models/page.py
+++ b/aircox/models/page.py
@@ -54,7 +54,7 @@ class PageQuerySet(InheritanceQuerySet):
self.filter(parent__id=id)
-class Page(models.Model):
+class BasePage(models.Model):
""" Base class for publishable content """
STATUS_DRAFT = 0x00
STATUS_PUBLISHED = 0x10
@@ -72,30 +72,22 @@ class Page(models.Model):
status = models.PositiveSmallIntegerField(
_('status'), default=STATUS_DRAFT, choices=STATUS_CHOICES,
)
- category = models.ForeignKey(
- Category, models.SET_NULL,
- verbose_name=_('category'), blank=True, null=True, db_index=True
- )
cover = FilerImageField(
on_delete=models.SET_NULL,
- verbose_name=_('Cover'), null=True, blank=True,
+ verbose_name=_('cover'), null=True, blank=True,
)
content = RichTextField(
_('content'), blank=True, null=True,
)
- pub_date = models.DateTimeField(blank=True, null=True)
- featured = models.BooleanField(
- _('featured'), default=False,
- )
- allow_comments = models.BooleanField(
- _('allow comments'), default=True,
- )
objects = PageQuerySet.as_manager()
detail_url_name = None
item_template_name = 'aircox/widgets/page_item.html'
+ class Meta:
+ abstract = True
+
def __str__(self):
return '{}'.format(self.title or self.pk)
@@ -106,10 +98,6 @@ class Page(models.Model):
count = Page.objects.filter(slug__startswith=self.slug).count()
if count:
self.slug += '-' + str(count)
- if self.is_published and self.pub_date is None:
- self.pub_date = tz.now()
- elif not self.is_published:
- self.pub_date = None
if not self.cover and self.parent:
self.cover = self.parent.cover
@@ -150,9 +138,71 @@ class Page(models.Model):
return cls(**cls.get_init_kwargs_from(page, **kwargs))
+class Page(BasePage):
+ """ Base Page model used for articles and other dated content. """
+ category = models.ForeignKey(
+ Category, models.SET_NULL,
+ verbose_name=_('category'), blank=True, null=True, db_index=True
+ )
+ pub_date = models.DateTimeField(blank=True, null=True)
+ featured = models.BooleanField(
+ _('featured'), default=False,
+ )
+ allow_comments = models.BooleanField(
+ _('allow comments'), default=True,
+ )
+
+ def save(self, *args, **kwargs):
+ if self.is_published and self.pub_date is None:
+ self.pub_date = tz.now()
+ elif not self.is_published:
+ self.pub_date = None
+ super().save(*args, **kwargs)
+
+
+class StaticPage(Page):
+ """ Static page that eventually can be attached to a specific view. """
+ VIEW_HOME = 0x00
+ VIEW_SCHEDULE = 0x01
+ VIEW_LOG = 0x02
+ VIEW_PROGRAMS = 0x03
+ VIEW_EPISODES = 0x04
+ VIEW_ARTICLES = 0x05
+
+ VIEW_CHOICES = (
+ (VIEW_HOME, _('Home Page')),
+ (VIEW_SCHEDULE, _('Schedule Page')),
+ (VIEW_LOG, _('Log Page')),
+ (VIEW_PROGRAMS, _('Programs list')),
+ (VIEW_EPISODES, _('Episodes list')),
+ (VIEW_ARTICLES, _('Articles list')),
+ )
+
+ view = models.SmallIntegerField(
+ _('attach to'), choices=VIEW_CHOICES, blank=True, null=True,
+ help_text=_('display this page content to related element'),
+ )
+ menu_title = models.CharField(_('menu title'), max_length=64, blank=True, null=True)
+
+ is_active = False
+
+ def render_menu_item(self, request, css_class='', active_class=''):
+ if active_class and request.path.startswith(self.url):
+ css_class += ' ' + active_class
+
+ if not self.url:
+ return self.text
+ elif not css_class:
+ return format_html('{}', self.url, self.text)
+ else:
+ return format_html('{}', self.url,
+ css_class, self.text)
+
+
class Comment(models.Model):
page = models.ForeignKey(
Page, models.CASCADE, verbose_name=_('related page'),
+ # TODO: allow_comment filter
)
nickname = models.CharField(_('nickname'), max_length=32)
email = models.EmailField(_('email'), max_length=32)
diff --git a/aircox/templates/admin/change_form.html b/aircox/templates/admin/change_form.html
index 0a1e388..7fedf81 100644
--- a/aircox/templates/admin/change_form.html
+++ b/aircox/templates/admin/change_form.html
@@ -8,11 +8,9 @@
› {{ opts.app_config.verbose_name }}
› {% if has_view_permission %}{{ opts.verbose_name_plural|capfirst }}{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
- {% with parent=parent|default:original.parent %}
{% if parent %}
› {{ parent.title }}
{% endif %}
- {% endwith %}
› {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
diff --git a/aircox/urls.py b/aircox/urls.py
index d19d5ad..d1d5d38 100755
--- a/aircox/urls.py
+++ b/aircox/urls.py
@@ -60,6 +60,12 @@ urls = [
path(_('publications/'),
views.PageListView.as_view(model=models.Page), name='page-list'),
+ path(_('pages/'),
+ views.PageListView.as_view(model=models.StaticPage), name='static-page-list'),
+
+ path(_('pages//'),
+ views.PageDetailView.as_view(), name='page-detail'),
+
path(_('programs/'), views.ProgramListView.as_view(model=models.Program),
name='program-list'),
path(_('programs//'),