From 19f7ceaf9fe7140734a68916990c2d0fa943edae Mon Sep 17 00:00:00 2001 From: bkfox Date: Mon, 6 Jun 2016 12:10:10 +0200 Subject: [PATCH] schedule section; page view with arbitrary content --- cms/admin.py | 4 +- cms/models.py | 12 ++++-- cms/routes.py | 12 +++--- cms/views.py | 60 +++++++++++++++++++++++------ cms/website.py | 19 +++++++++ website/sections.py | 93 +++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 169 insertions(+), 31 deletions(-) diff --git a/cms/admin.py b/cms/admin.py index 2c18556..b6db0e4 100644 --- a/cms/admin.py +++ b/cms/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin import aircox.cms.models as models -admin.site.register(cms.Article) -admin.site.register(cms.Comment) +admin.site.register(models.Article) +admin.site.register(models.Comment) diff --git a/cms/models.py b/cms/models.py index b3a8fe1..1fc92ad 100644 --- a/cms/models.py +++ b/cms/models.py @@ -38,10 +38,12 @@ class Routable: ) @classmethod - def route_url(cl, route, kwargs = None): + def route_url(cl, route, **kwargs): name = cl._website.name_of_model(cl) name = route.get_view_name(name) - return reverse(name, kwargs = kwargs) + r = reverse(name, kwargs = kwargs) + return r + class Comment(models.Model, Routable): thread_type = models.ForeignKey( @@ -162,8 +164,10 @@ class Post (models.Model, Routable): return qs def detail_url(self): - return self.route_url(routes.DetailRoute, - { 'pk': self.pk, 'slug': slugify(self.title) }) + return self.route_url( + routes.DetailRoute, + pk = self.pk, slug = slugify(self.title) + ) def get_object_list(self, request, object, **kwargs): type = ContentType.objects.get_for_model(object) diff --git a/cms/routes.py b/cms/routes.py index 84ef7a5..447741d 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -1,4 +1,5 @@ from django.db import models +from django.utils import timezone as tz from django.conf.urls import url from django.contrib.contenttypes.models import ContentType from django.utils import timezone @@ -137,8 +138,8 @@ class DateRoute(Route): name = 'date' url_args = [ ('year', '[0-9]{4}'), - ('month', '[0-9]{2}'), - ('day', '[0-9]{1,2}'), + ('month', '[0-1]?[0-9]'), + ('day', '[0-3]?[0-9]'), ] @classmethod @@ -151,11 +152,10 @@ class DateRoute(Route): @classmethod def get_title(cl, model, request, year, month, day, **kwargs): - return _('%(model)s of %(year)/%(month)/%(day)') % { + date = tz.datetime(year = int(year), month = int(month), day = int(day)) + return _('%(model)s of %(date)s') % { 'model': model._meta.verbose_name_plural, - 'year': year, - 'month': month, - 'day': day + 'date': date.strftime('%A %d %B %Y'), } diff --git a/cms/views.py b/cms/views.py index 1295e7f..62ee0da 100644 --- a/cms/views.py +++ b/cms/views.py @@ -1,7 +1,7 @@ from django.templatetags.static import static from django.template.loader import render_to_string from django.views.generic import ListView, DetailView -from django.views.generic.base import View +from django.views.generic.base import View, TemplateView from django.utils.translation import ugettext as _, ugettext_lazy from django.contrib import messages from django.http import Http404 @@ -13,7 +13,8 @@ class PostBaseView: website = None # corresponding website title = '' # title of the page embed = False # page is embed (if True, only post content is printed - classes = '' # extra classes for the content + attrs = '' # attr for the HTML element of the content + css_classes = ''# css classes for the HTML element of the content def get_base_context(self, **kwargs): """ @@ -108,11 +109,13 @@ class PostListView(PostBaseView, ListView): self.route.get_title(self.model, self.request, **self.kwargs) - context['title'] = title - context['base_template'] = 'aircox/cms/website.html' - context['css_class'] = 'list' if not self.css_class else \ - 'list ' + self.css_class - context['list'] = self.list + context.update({ + 'title': title, + 'base_template': 'aircox/cms/website.html', + 'css_class': 'list' if not self.css_class else \ + 'list ' + self.css_class, + 'list': self.list, + }) # FIXME: list.url = if self.route: self.model(self.route, self.kwargs) else '' return context @@ -155,11 +158,13 @@ class PostDetailView(DetailView, PostBaseView): context.update(self.get_base_context()) kwargs['object'] = self.object - context['content'] = ''.join([ - section.get(request = self.request, **kwargs) - for section in self.sections - ]) - context['css_class'] = 'detail' + context.update({ + 'content': ''.join([ + section.get(request = self.request, **kwargs) + for section in self.sections + ]), + 'css_class': 'detail', + }) return context def post(self, request, *args, **kwargs): @@ -176,3 +181,34 @@ class PostDetailView(DetailView, PostBaseView): return self.get(request, *args, **kwargs) +class PageView(TemplateView, PostBaseView): + """ + A simple page view. Used to render pages that have arbitrary content + without linked post object. + """ + template_name = 'aircox/cms/detail.html' + + sections = [] + css_class = 'page' + + def __init__(self, *args, **kwargs): + css_class = 'css_class' in kwargs and kwargs.pop('css_class') + if css_class: + self.css_class += ' ' + css_class + super().__init__(*args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context.update(self.get_base_context()) + + context.update({ + 'title': self.title, + 'content': ''.join([ + section.get(request = self.request, **kwargs) + for section in self.sections + ]), + }) + return context + + + diff --git a/cms/website.py b/cms/website.py index 93a4f01..bc457fc 100644 --- a/cms/website.py +++ b/cms/website.py @@ -1,3 +1,6 @@ +from django.utils.text import slugify +from django.conf.urls import url + import aircox.cms.routes as routes import aircox.cms.views as views @@ -104,6 +107,22 @@ class Website: self.urls += [ route.as_url(name, view) for route in routes ] self.registry[name] = model + def register_page(self, name, view = views.PageView, path = None, + **view_kwargs): + """ + Register a page that is accessible to the given path. If path is None, + use a slug of the name. + """ + view = view.as_view( + website = self, + **view_kwargs + ) + self.urls.append(url( + slugify(name) if path is None else path, + view = view, + name = name, + )) + def register(self, name, model, sections = None, routes = None, list_view = views.PostListView, detail_view = views.PostDetailView, diff --git a/website/sections.py b/website/sections.py index 9ce1741..09b9b90 100644 --- a/website/sections.py +++ b/website/sections.py @@ -6,7 +6,7 @@ import aircox.cms.models as cms import aircox.cms.routes as routes import aircox.cms.sections as sections -import website.models as models +import aircox.website.models as models class Diffusions(sections.List): @@ -22,12 +22,14 @@ class Diffusions(sections.List): super().__init__(*args, **kwargs) self.__dict__.update(kwargs) - def get_diffs(self): + def get_diffs(self, **filter_args): qs = programs.Diffusion.objects.filter( type = programs.Diffusion.Type.normal ) if self.object: qs = qs.filter(program = self.object.related) + if filter_args: + qs = qs.filter(**filter_args).order_by('start') r = [] if self.next_count: @@ -70,10 +72,10 @@ class Diffusions(sections.List): @property def url(self): if self.object: - return models.Diffusion.route_url(routes.ThreadRoute, { - 'pk': self.object.id, - 'thread_model': 'program', - }) + return models.Diffusion.route_url(routes.ThreadRoute, + pk = self.object.id, + thread_model = 'program', + ) return models.Diffusion.route_url(routes.AllRoute) @property @@ -81,7 +83,6 @@ class Diffusions(sections.List): if not self.show_schedule: return None - def str_sched(sched): info = ' (' + _('rerun of %(day)s') % { 'day': sched.initial.date.strftime('%A') @@ -112,6 +113,84 @@ class Playlist(sections.List): for track in tracks ] +class Schedule(Diffusions): + """ + Schedule printing diffusions starting at the given date + + * date: if set use this date instead of now; + * days: number of days to show; + * time_format: force format of the date in schedule header; + """ + date = None + days = 7 + time_format = '%a. %d' + + def get_diffs(self): + date = self.date or tz.datetime.now() + return super().get_diffs( + start__year = date.year, + start__month = date.month, + start__day = date.day, + ) + + @property + def header(self): + date = self.date or tz.datetime.now() + date.replace(hour = 0, minute = 0, second = 0, microsecond = 0) + curr = date - tz.timedelta(days=date.weekday()) + last = curr + tz.timedelta(days=7) + + r = """ + + """ + while curr < last: + r += \ + '{title}' \ + .format( + title = curr.strftime(self.time_format), + extra = ' class="selected"' if curr == date else '', + url = models.Diffusion.route_url( + routes.DateRoute, + year = curr.year, month = curr.month, day = curr.day, + ) + ) + curr += tz.timedelta(days=1) + return r + + + #class DatesOfDiffusion(sections.List): # title = _('Dates of diffusion') #