add website application

This commit is contained in:
bkfox 2016-06-02 01:32:58 +02:00
parent 392d48ac0c
commit fcb1866f2e
8 changed files with 241 additions and 2 deletions

View File

@ -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 We aims here to automatize most common tasks and to ease website
configuration. configuration.
# Dependencies
* ```django-taggit```: publications tags
Note: this application can be used outside Aircox if needed.
# Architecture # Architecture
A **Website** holds all required informations to run the server instance. It 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. is used to register all kind of posts, routes to the views, menus, etc.

View File

@ -1,6 +1,8 @@
from django.contrib import admin from django.contrib import admin
import aircox.cms.models as models
admin.site.register(cms.Article)
admin.site.register(cms.Comment)

View File

@ -75,6 +75,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% if object_list %}
{% if page_obj or list.url %} {% if page_obj or list.url %}
<nav> <nav>
{% if not page_obj or embed %} {% if not page_obj or embed %}
@ -117,5 +118,6 @@
{% endif %} {% endif %}
</nav> </nav>
{% endif %} {% endif %}
{% endif %}
{% endblock %} {% endblock %}

30
website/README.md Normal file
View File

@ -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.

0
website/__init__.py Normal file
View File

8
website/admin.py Normal file
View File

@ -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)

52
website/models.py Normal file
View File

@ -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

140
website/sections.py Normal file
View File

@ -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 = ' <span class="info">(' + _('rerun of %(day)s') % {
'day': sched.initial.date.strftime('%A')
} + ')</span>' 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
#