From fcb1866f2e888929e8e2912fd67d5873a0f69580 Mon Sep 17 00:00:00 2001 From: bkfox Date: Thu, 2 Jun 2016 01:32:58 +0200 Subject: [PATCH] add website application --- cms/README.md | 5 ++ cms/admin.py | 6 +- cms/templates/aircox/cms/list.html | 2 + website/README.md | 30 +++++++ website/__init__.py | 0 website/admin.py | 8 ++ website/models.py | 52 +++++++++++ website/sections.py | 140 +++++++++++++++++++++++++++++ 8 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 website/README.md create mode 100644 website/__init__.py create mode 100644 website/admin.py create mode 100644 website/models.py create mode 100644 website/sections.py diff --git a/cms/README.md b/cms/README.md index e18d852..ffd080a 100644 --- a/cms/README.md +++ b/cms/README.md @@ -14,6 +14,11 @@ Simple CMS generator used in Aircox. Main features includes: We aims here to automatize most common tasks and to ease website configuration. +# Dependencies +* ```django-taggit```: publications tags + +Note: this application can be used outside Aircox if needed. + # Architecture A **Website** holds all required informations to run the server instance. It is used to register all kind of posts, routes to the views, menus, etc. diff --git a/cms/admin.py b/cms/admin.py index 8bed95d..2c18556 100644 --- a/cms/admin.py +++ b/cms/admin.py @@ -1,6 +1,8 @@ from django.contrib import admin - - +import aircox.cms.models as models + +admin.site.register(cms.Article) +admin.site.register(cms.Comment) diff --git a/cms/templates/aircox/cms/list.html b/cms/templates/aircox/cms/list.html index b3cda21..e161d5a 100644 --- a/cms/templates/aircox/cms/list.html +++ b/cms/templates/aircox/cms/list.html @@ -75,6 +75,7 @@ {% endfor %} +{% if object_list %} {% if page_obj or list.url %} {% endif %} +{% endif %} {% endblock %} diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000..363bba7 --- /dev/null +++ b/website/README.md @@ -0,0 +1,30 @@ +# Website +Application that propose a set of different tools that might be common to +different radio projects. This application has been started to avoid to +pollute *aircox.cms* with aircox specific code and models that might not +be used in other cases. + +We define here different models and sections that can be used to construct +a website in a fast and simple manner. + +# Dependencies +* ```django-suit```: admin interface; +* ```django-autocomplete-light```: autocompletion in the admin interface; +* ```aircox.cms```, ```aircox.programs``` + +# Features +## Models +* **Program**: publication related to a program; +* **Diffusion**: publication related to an initial Diffusion; + + +## Sections +* **Diffusions**: generic section list to retrieve diffusions by date, related + or not to a specific Program. If wanted, can show schedule in the header of + the section (with indication of reruns). +* **Playlist**: playlist of a given Diffusion + +## Admin +Register all models declared upper, uses django-suit features in order to manage +some fields and autocompletion. + diff --git a/website/__init__.py b/website/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/website/admin.py b/website/admin.py new file mode 100644 index 0000000..d048aef --- /dev/null +++ b/website/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +import aircox.website.models as models + +admin.site.register(models.Program) +admin.site.register(models.Diffusion) + + diff --git a/website/models.py b/website/models.py new file mode 100644 index 0000000..1d0cea3 --- /dev/null +++ b/website/models.py @@ -0,0 +1,52 @@ +from django.db import models +from django.utils.translation import ugettext as _, ugettext_lazy + +from aircox.cms.models import RelatedPost, Article +import aircox.programs.models as programs + +class Program (RelatedPost): + url = models.URLField(_('website'), blank=True, null=True) + # rss = models.URLField() + email = models.EmailField( + _('email'), blank=True, null=True, + help_text=_('contact address, stays private') + ) + + class Relation: + model = programs.Program + bindings = { + 'title': 'name', + } + rel_to_post = True + auto_create = True + +class Diffusion (RelatedPost): + class Relation: + model = programs.Diffusion + bindings = { + 'thread': 'program', + 'date': 'start', + } + fields_args = { + 'limit_choice_to': { + 'initial': None + } + } + rel_to_post = True + auto_create = True + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.thread: + if not self.title: + self.title = _('{name} on {first_diff}').format( + self.related.program.name, + self.related.start.strftime('%A %d %B') + ) + if not self.content: + self.content = self.thread.content + if not self.image: + self.image = self.thread.image + if not self.tags and self.pk: + self.tags = self.thread.tags + diff --git a/website/sections.py b/website/sections.py new file mode 100644 index 0000000..9ce1741 --- /dev/null +++ b/website/sections.py @@ -0,0 +1,140 @@ +from django.utils import timezone as tz +from django.utils.translation import ugettext as _, ugettext_lazy + +import aircox.programs.models as programs +import aircox.cms.models as cms +import aircox.cms.routes as routes +import aircox.cms.sections as sections + +import website.models as models + + +class Diffusions(sections.List): + """ + Section that print diffusions. When rendering, if there is no post yet + associated, use the programs' article. + """ + next_count = 5 + prev_count = 5 + show_schedule = False + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.__dict__.update(kwargs) + + def get_diffs(self): + qs = programs.Diffusion.objects.filter( + type = programs.Diffusion.Type.normal + ) + if self.object: + qs = qs.filter(program = self.object.related) + + r = [] + if self.next_count: + r += list(programs.Diffusion.get(next=True, queryset = qs) + .order_by('-start')[:self.next_count]) + if self.prev_count: + r += list(programs.Diffusion.get(prev=True, queryset = qs) + .order_by('-start')[:self.prev_count]) + return r + + def get_object_list(self): + diffs = self.get_diffs() + + posts = models.Diffusion.objects.filter(related__in = diffs) + r = [] + for diff in diffs: + diff_ = diff.initial if diff.initial else diff + post = next((x for x in posts if x.related == diff_), None) + if not post: + post = sections.ListItem(date = diff.start) + else: + post = sections.ListItem(post=post) + post.date = diff.start + + if diff.initial: + post.info = _('rerun of %(day)s') % { + 'day': diff.initial.date.strftime('%A %d/%m') + } + + if self.object: + post.update(self.object) + else: + thread = models.Program.objects. \ + filter(related = diff.program, published = True) + if thread: + post.update(thread[0]) + r.append(post) + return [ sections.ListItem(post=post) for post in r ] + + @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.AllRoute) + + @property + def header(self): + if not self.show_schedule: + return None + + + def str_sched(sched): + info = ' (' + _('rerun of %(day)s') % { + 'day': sched.initial.date.strftime('%A') + } + ')' if sched.initial else '' + + text = _('%(day)s at %(time)s, %(freq)s') % { + 'day': sched.date.strftime('%A'), + 'time': sched.date.strftime('%H:%M'), + 'freq': sched.get_frequency_display(), + } + return text + info + + return ' / \n'.join([str_sched(sched) + for sched in programs.Schedule.objects \ + .filter(program = self.object.related.pk) + ]) + + +class Playlist(sections.List): + title = _('Playlist') + message_empty = '' + + def get_object_list(self): + tracks = programs.Track.objects \ + .filter(diffusion = self.object.related) \ + .order_by('position') + return [ sections.ListItem(title=track.title, content=track.artist) + for track in tracks ] + + +#class DatesOfDiffusion(sections.List): +# title = _('Dates of diffusion') +# +# def get_object_list(self): +# diffs = list(programs.Diffusion.objects. \ +# filter(initial = self.object.related). \ +# exclude(type = programs.Diffusion.Type.unconfirmed) +# ) +# diffs.append(self.object.related) +# +# items = [] +# for diff in sorted(diffs, key = lambda d: d.date, reverse = True): +# info = '' +# if diff.initial: +# info = _('rerun') +# if diff.type == programs.Diffusion.Type.canceled: +# info += ' ' + _('canceled') +# items.append( +# sections.List.Item(None, diff.start.strftime('%c'), info, None, +# 'canceled') +# ) +# return items +# +## TODO sounds +# +