forked from rc/aircox
		
	start static pages
This commit is contained in:
		@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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]
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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):
 | 
			
		||||
 | 
			
		||||
@ -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('<a href="{}">{}</a>', self.url, self.text)
 | 
			
		||||
        else:
 | 
			
		||||
            return format_html('<a href="{}" class="{}">{}</a>', 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)
 | 
			
		||||
 | 
			
		||||
@ -8,11 +8,9 @@
 | 
			
		||||
    › <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
 | 
			
		||||
    › {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
 | 
			
		||||
 | 
			
		||||
    {% with parent=parent|default:original.parent %}
 | 
			
		||||
    {% if parent %}
 | 
			
		||||
    › <a href="{% url opts|admin_urlname:"changelist" %}?parent={{parent.id}}">{{ parent.title }}</a>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
 | 
			
		||||
    › {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -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/<slug:slug>/'),
 | 
			
		||||
         views.PageDetailView.as_view(), name='page-detail'),
 | 
			
		||||
 | 
			
		||||
    path(_('programs/'), views.ProgramListView.as_view(model=models.Program),
 | 
			
		||||
         name='program-list'),
 | 
			
		||||
    path(_('programs/<slug:slug>/'),
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user