add website application
This commit is contained in:
parent
392d48ac0c
commit
fcb1866f2e
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
30
website/README.md
Normal 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
0
website/__init__.py
Normal file
8
website/admin.py
Normal file
8
website/admin.py
Normal 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
52
website/models.py
Normal 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
140
website/sections.py
Normal 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
|
||||||
|
#
|
||||||
|
|
Loading…
Reference in New Issue
Block a user