work on website + page becomes concrete

This commit is contained in:
bkfox
2019-09-05 14:12:12 +02:00
parent 595af5a69d
commit c46f006379
88 changed files with 476 additions and 9823 deletions

View File

@ -1,6 +1,6 @@
from . import api
from .article import ArticleListView
from .article import ArticleDetailView, ArticleListView
from .base import BaseView
from .episode import EpisodeDetailView, EpisodeListView, TimetableView
from .log import LogListView

View File

@ -1,16 +1,36 @@
from ..models import Article
from .program import ProgramPageListView
from ..models import Article, Program
from .page import ParentMixin, PageDetailView, PageListView
__all__ = ['ArticleListView']
__all__ = ['ArticleDetailView', 'ArticleListView']
class ArticleListView(ProgramPageListView):
class ArticleDetailView(PageDetailView):
show_side_nav = True
model = Article
def get_side_queryset(self):
qs = Article.objects.select_related('cover') \
.filter(is_static=False) \
.order_by('-date')
return qs
def get_context_data(self, **kwargs):
if self.object.program is not None:
kwargs.setdefault('parent', self.object.program)
return super().get_context_data(**kwargs)
class ArticleListView(ParentMixin, PageListView):
model = Article
template_name = 'aircox/article_list.html'
show_headline = True
is_static = False
def get_queryset(self):
return super().get_queryset(is_static=self.is_static)
parent_model = Program
fk_parent = 'program'
def get_queryset(self):
return super().get_queryset().filter(is_static=self.is_static)

View File

@ -6,17 +6,20 @@ from django.views.generic.base import TemplateResponseMixin, ContextMixin
from ..utils import Redirect
__all__ = ['BaseView', 'PageView']
__all__ = ['BaseView']
class BaseView(TemplateResponseMixin, ContextMixin):
show_side_nav = False
""" Show side navigation """
title = None
""" Page title """
cover = None
""" Page cover """
show_side_nav = False
""" Show side navigation """
list_count = 5
""" Item count for small lists displayed on page. """
@property
def station(self):
return self.request.station
@ -24,14 +27,24 @@ class BaseView(TemplateResponseMixin, ContextMixin):
def get_queryset(self):
return super().get_queryset().station(self.station)
def get_context_data(self, **kwargs):
def get_side_queryset(self):
""" Return a queryset of items to render on the side nav. """
return None
def get_context_data(self, side_items=None, **kwargs):
kwargs.setdefault('station', self.station)
kwargs.setdefault('cover', self.cover)
kwargs.setdefault('show_side_nav', self.show_side_nav)
show_side_nav = kwargs.setdefault('show_side_nav', self.show_side_nav)
if show_side_nav and side_items is None:
side_items = self.get_side_queryset()
side_items = None if side_items is None else \
side_items[:self.list_count]
if not 'audio_streams' in kwargs:
streams = self.station.audio_streams
streams = streams and streams.split('\n')
kwargs['audio_streams'] = streams
return super().get_context_data(**kwargs)
return super().get_context_data(side_items=side_items, **kwargs)

View File

@ -1,16 +1,16 @@
from collections import OrderedDict
import datetime
from django.db.models import OuterRef, Subquery
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from ..models import Diffusion, Episode, Page, Program, Sound
from ..converters import WeekConverter
from ..models import Diffusion, Episode, Program, Sound
from .base import BaseView
from .program import ProgramPageDetailView, ProgramPageListView
from .program import ProgramPageDetailView
from .page import ParentMixin, PageListView
__all__ = ['EpisodeDetailView', 'DiffusionListView', 'TimetableView']
__all__ = ['EpisodeDetailView', 'EpisodeListView', 'TimetableView']
class EpisodeDetailView(ProgramPageDetailView):
@ -20,8 +20,9 @@ class EpisodeDetailView(ProgramPageDetailView):
return Sound.objects.diffusion(diffusion).podcasts()
def get_context_data(self, **kwargs):
kwargs.setdefault('program', self.object.program)
kwargs.setdefault('parent', kwargs['program'])
self.program = kwargs.setdefault('program', self.object.program)
kwargs.setdefault('parent', self.program)
if not 'tracks' in kwargs:
kwargs['tracks'] = self.object.track_set.order_by('position')
if not 'podcasts' in kwargs:
@ -29,12 +30,15 @@ class EpisodeDetailView(ProgramPageDetailView):
return super().get_context_data(**kwargs)
class EpisodeListView(ProgramPageListView):
class EpisodeListView(ParentMixin, PageListView):
model = Episode
template_name = 'aircox/diffusion_list.html'
item_template_name = 'aircox/episode_item.html'
show_headline = True
parent_model = Program
fk_parent = 'program'
class TimetableView(BaseView, ListView):
""" View for timetables """

View File

@ -1,6 +1,7 @@
from django.core.exceptions import FieldDoesNotExist
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.views.generic import DetailView, ListView
from ..models import Category
@ -8,41 +9,48 @@ from ..utils import Redirect
from .base import BaseView
__all__ = ['PageDetailView', 'PageListView']
__all__ = ['ParentMixin', 'PageDetailView', 'PageListView']
class PageDetailView(BaseView, DetailView):
""" Base view class for pages. """
context_object_name = 'page'
class ParentMixin:
"""
Optional parent page for a list view. Parent is fetched and passed to the
template context when `parent_model` is provided (queryset is filtered by
parent page in such case).
"""
parent_model = None
""" Parent model """
parent_url_kwarg = 'parent_slug'
""" Url lookup argument """
parent_field = 'slug'
""" Parent field for url lookup """
fk_parent = 'page'
""" Page foreign key to the parent """
parent = None
""" Parent page object """
def get_parent(self, request, *args, **kwargs):
if self.parent_model is None or self.parent_url_kwarg not in kwargs:
return
lookup = {self.parent_field: kwargs[self.parent_url_kwarg]}
return get_object_or_404(
self.parent_model.objects.select_related('cover'), **lookup)
def get(self, request, *args, **kwargs):
self.parent = self.get_parent(request, *args, **kwargs)
return super().get(request, *args, **kwargs)
def get_queryset(self):
return super().get_queryset().select_related('cover', 'category')
# This should not exists: it allows mapping not published pages
# or it should be only used for trashed pages.
def not_published_redirect(self, page):
"""
When a page is not published, redirect to the returned url instead
of an HTTP 404 code. """
return None
def get_object(self):
obj = super().get_object()
if not obj.is_published:
redirect_url = self.not_published_redirect(obj)
if redirect_url:
raise Redirect(redirect_url)
raise Http404('%s not found' % self.model._meta.verbose_name)
return obj
if self.parent is not None:
lookup = {self.fk_parent: self.parent}
return super().get_queryset().filter(**lookup)
return super().get_queryset()
def get_context_data(self, **kwargs):
#if kwargs.get('regions') is None:
# contents = contents_for_item(
# page, page_renderer._renderers.keys())
# kwargs['regions'] = contents.render_regions(page_renderer)
page = kwargs.setdefault('page', self.object)
kwargs.setdefault('title', page.title)
kwargs.setdefault('cover', page.cover)
parent = kwargs.setdefault('parent', self.parent)
if parent is not None:
kwargs.setdefault('cover', parent.cover)
return super().get_context_data(**kwargs)
@ -84,4 +92,35 @@ class PageListView(BaseView, ListView):
return super().get_context_data(**kwargs)
class PageDetailView(BaseView, DetailView):
""" Base view class for pages. """
context_object_name = 'page'
def get_queryset(self):
return super().get_queryset().select_related('cover', 'category')
# This should not exists: it allows mapping not published pages
# or it should be only used for trashed pages.
def not_published_redirect(self, page):
"""
When a page is not published, redirect to the returned url instead
of an HTTP 404 code. """
return None
def get_object(self):
obj = super().get_object()
if not obj.is_published:
redirect_url = self.not_published_redirect(obj)
if redirect_url:
raise Redirect(redirect_url)
raise Http404('%s not found' % self.model._meta.verbose_name)
return obj
def get_context_data(self, **kwargs):
page = kwargs.setdefault('page', self.object)
kwargs.setdefault('title', page.title)
kwargs.setdefault('cover', page.cover)
return super().get_context_data(**kwargs)

View File

@ -12,53 +12,25 @@ class ProgramPageDetailView(PageDetailView):
"""
Base view class for a page that is displayed as a program's child page.
"""
program = None
show_side_nav = True
list_count = 5
def get_episodes_queryset(self, program):
return program.episode_set.published().order_by('-date')
def get_context_data(self, program, episodes=None, **kwargs):
if episodes is None:
episodes = self.get_episodes_queryset(program)
return super().get_context_data(
program=program, episodes=episodes[:self.list_count], **kwargs)
class ProgramPageListView(PageListView):
"""
Base list view class rendering pages as a program's child page.
Retrieved program from it slug provided by `kwargs['program_slug']`.
This view class can be used with or without providing a program.
"""
program = None
def get(self, request, *args, **kwargs):
slug = kwargs.get('program_slug', None)
if slug is not None:
self.program = get_object_or_404(
Program.objects.select_related('cover'), slug=slug)
return super().get(request, *args, **kwargs)
def get_queryset(self):
return super().get_queryset().filter(program=self.program) \
if self.program else super().get_queryset()
def get_context_data(self, **kwargs):
program = kwargs.setdefault('program', self.program)
if program is not None:
kwargs.setdefault('cover', program.cover)
kwargs.setdefault('parent', program)
return super().get_context_data(**kwargs)
def get_side_queryset(self):
return self.program.episode_set.published().order_by('-date')
class ProgramDetailView(ProgramPageDetailView):
model = Program
def get_articles_queryset(self, program):
return program.article_set.published().order_by('-date')
def get_articles_queryset(self):
return self.program.article_set.published().order_by('-date')
def get_context_data(self, **kwargs):
kwargs.setdefault('program', self.object)
self.program = kwargs.setdefault('program', self.object)
if 'articles' not in kwargs:
kwargs['articles'] = \
self.get_articles_queryset()[:self.list_count]
return super().get_context_data(**kwargs)