work on it
This commit is contained in:
parent
7c8814e164
commit
fff4801ac7
|
@ -9,12 +9,12 @@ from .playlist import TracksInline
|
||||||
class SoundAdmin(admin.ModelAdmin):
|
class SoundAdmin(admin.ModelAdmin):
|
||||||
fields = None
|
fields = None
|
||||||
list_display = ['id', 'name', 'program', 'type', 'duration', 'mtime',
|
list_display = ['id', 'name', 'program', 'type', 'duration', 'mtime',
|
||||||
'public', 'good_quality', 'path']
|
'is_public', 'is_good_quality', 'path']
|
||||||
list_filter = ('program', 'type', 'good_quality', 'public')
|
list_filter = ('program', 'type', 'is_good_quality', 'is_public')
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None, {'fields': ['name', 'path', 'type', 'program', 'diffusion']}),
|
(None, {'fields': ['name', 'path', 'type', 'program', 'diffusion']}),
|
||||||
(None, {'fields': ['embed', 'duration', 'public', 'mtime']}),
|
(None, {'fields': ['embed', 'duration', 'is_public', 'mtime']}),
|
||||||
(None, {'fields': ['good_quality']})
|
(None, {'fields': ['is_good_quality']})
|
||||||
]
|
]
|
||||||
readonly_fields = ('path', 'duration',)
|
readonly_fields = ('path', 'duration',)
|
||||||
inlines = [TracksInline]
|
inlines = [TracksInline]
|
||||||
|
|
|
@ -327,18 +327,17 @@ class Command(BaseCommand):
|
||||||
"""
|
"""
|
||||||
Check all files where quality has been set to bad
|
Check all files where quality has been set to bad
|
||||||
"""
|
"""
|
||||||
import aircox.management.commands.sounds_quality_check \
|
import aircox.management.commands.sounds_quality_check as quality_check
|
||||||
as quality_check
|
|
||||||
|
|
||||||
# get available sound files
|
# get available sound files
|
||||||
sounds = Sound.objects.filter(good_quality=False) \
|
sounds = Sound.objects.filter(is_good_quality=False) \
|
||||||
.exclude(type=Sound.Type.removed)
|
.exclude(type=Sound.Type.removed)
|
||||||
if check:
|
if check:
|
||||||
self.check_sounds(sounds)
|
self.check_sounds(sounds)
|
||||||
|
|
||||||
files = [
|
files = [
|
||||||
sound.path for sound in sounds
|
sound.path for sound in sounds
|
||||||
if os.path.exists(sound.path) and sound.good_quality is None
|
if os.path.exists(sound.path) and sound.is_good_quality is None
|
||||||
]
|
]
|
||||||
|
|
||||||
# check quality
|
# check quality
|
||||||
|
@ -358,7 +357,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
for sound_info in cmd.good:
|
for sound_info in cmd.good:
|
||||||
sound = Sound.objects.get(path=sound_info.path)
|
sound = Sound.objects.get(path=sound_info.path)
|
||||||
sound.good_quality = True
|
sound.is_good_quality = True
|
||||||
update_stats(sound_info, sound)
|
update_stats(sound_info, sound)
|
||||||
sound.save(check=False)
|
sound.save(check=False)
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,6 @@ class Program(models.Model):
|
||||||
.update(path=Concat('path', Substr(F('path'), len(path_))))
|
.update(path=Concat('path', Substr(F('path'), len(path_))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Stream(models.Model):
|
class Stream(models.Model):
|
||||||
"""
|
"""
|
||||||
When there are no program scheduled, it is possible to play sounds
|
When there are no program scheduled, it is possible to play sounds
|
||||||
|
@ -522,74 +521,54 @@ class Schedule(models.Model):
|
||||||
Return a new datetime with schedule time. Timezone is handled
|
Return a new datetime with schedule time. Timezone is handled
|
||||||
using `schedule.timezone`.
|
using `schedule.timezone`.
|
||||||
"""
|
"""
|
||||||
time = self.time or self.date
|
date = tz.datetime.combine(date, self.time)
|
||||||
date = tz.datetime(date.year, date.month, date.day,
|
return self.tz.normalize(self.tz.localize(date))
|
||||||
time.hour, time.minute, 0, 0)
|
|
||||||
date = self.tz.localize(date)
|
|
||||||
date = self.tz.normalize(date)
|
|
||||||
|
|
||||||
return date
|
def dates_of_month(self, date):
|
||||||
|
|
||||||
def dates_of_month(self, date=None):
|
|
||||||
"""
|
"""
|
||||||
Return a list with all matching dates of date.month (=today)
|
Return a list with all matching dates of date.month (=today)
|
||||||
Ensure timezone awareness.
|
Ensure timezone awareness.
|
||||||
|
|
||||||
|
:param datetime.date date: month and year
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.frequency == Schedule.Frequency.ponctual:
|
if self.frequency == Schedule.Frequency.ponctual:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# first day of month
|
sched_wday, freq = self.date.weekday(), self.frequency
|
||||||
date = utils.date_or_default(date, datetime.date).replace(day=1)
|
date = date.replace(day=1)
|
||||||
freq = self.frequency
|
|
||||||
|
|
||||||
# last of the month
|
# last of the month
|
||||||
|
|
||||||
if freq == Schedule.Frequency.last:
|
if freq == Schedule.Frequency.last:
|
||||||
date = date.replace(
|
date = date.replace(
|
||||||
day=calendar.monthrange(date.year, date.month)[1])
|
day=calendar.monthrange(date.year, date.month)[1])
|
||||||
|
date_wday = date.weekday()
|
||||||
|
|
||||||
# end of month before the wanted weekday: move one week back
|
# end of month before the wanted weekday: move one week back
|
||||||
|
|
||||||
if date.weekday() < self.date.weekday():
|
if date_wday < sched_wday:
|
||||||
date -= tz.timedelta(days=7)
|
date -= tz.timedelta(days=7)
|
||||||
|
date += tz.timedelta(days=sched_wday - date_wday)
|
||||||
delta = self.date.weekday() - date.weekday()
|
|
||||||
date += tz.timedelta(days=delta)
|
|
||||||
|
|
||||||
return [self.normalize(date)]
|
return [self.normalize(date)]
|
||||||
|
|
||||||
# move to the first day of the month that matches the schedule's weekday
|
# move to the first day of the month that matches the schedule's weekday
|
||||||
# check on SO#3284452 for the formula
|
# check on SO#3284452 for the formula
|
||||||
first_weekday = date.weekday()
|
date_wday, month = date.weekday(), date.month
|
||||||
sched_weekday = self.date.weekday()
|
date += tz.timedelta(days=(7 if date_wday > sched_wday else 0) -
|
||||||
date += tz.timedelta(days=(7 if first_weekday > sched_weekday else 0)
|
date_wday + sched_wday)
|
||||||
- first_weekday + sched_weekday)
|
|
||||||
month = date.month
|
|
||||||
|
|
||||||
dates = []
|
|
||||||
|
|
||||||
if freq == Schedule.Frequency.one_on_two:
|
if freq == Schedule.Frequency.one_on_two:
|
||||||
# check date base on a diff of dates base on a 14 days delta
|
# - adjust date with modulo 14 (= 2 weeks in days)
|
||||||
diff = utils.cast_date(date, datetime.date) - \
|
# - there are max 3 "weeks on two" per month
|
||||||
utils.cast_date(self.date, datetime.date)
|
if (date - self.date).days % 14:
|
||||||
|
|
||||||
if diff.days % 14:
|
|
||||||
date += tz.timedelta(days=7)
|
date += tz.timedelta(days=7)
|
||||||
|
dates = (date + tz.timedelta(days=14*i) for i in range(0, 3))
|
||||||
while date.month == month:
|
|
||||||
dates.append(date)
|
|
||||||
date += tz.timedelta(days=14)
|
|
||||||
else:
|
else:
|
||||||
week = 0
|
dates = (date + tz.timedelta(days=7*week) for week in range(0, 5)
|
||||||
|
if freq & (0b1 << week))
|
||||||
|
|
||||||
while week < 5 and date.month == month:
|
return [self.normalize(date) for date in dates if date.month == month]
|
||||||
if freq & (0b1 << week):
|
|
||||||
dates.append(date)
|
|
||||||
date += tz.timedelta(days=7)
|
|
||||||
week += 1
|
|
||||||
|
|
||||||
return [self.normalize(date) for date in dates]
|
|
||||||
|
|
||||||
def diffusions_of_month(self, date=None, exclude_saved=False):
|
def diffusions_of_month(self, date=None, exclude_saved=False):
|
||||||
"""
|
"""
|
||||||
|
@ -625,6 +604,7 @@ class Schedule(models.Model):
|
||||||
|
|
||||||
# FIXME: daylight saving bug: delta misses an hour when diffusion and
|
# FIXME: daylight saving bug: delta misses an hour when diffusion and
|
||||||
# rerun are not on the same daylight-saving timezone
|
# rerun are not on the same daylight-saving timezone
|
||||||
|
# -> solution: add rerun=True param, and gen reruns from initial for each
|
||||||
diffusions += [
|
diffusions += [
|
||||||
Diffusion(
|
Diffusion(
|
||||||
program=self.program,
|
program=self.program,
|
||||||
|
@ -922,6 +902,15 @@ class Diffusion(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SoundQuerySet(models.QuerySet):
|
||||||
|
def podcasts(self):
|
||||||
|
""" Return sound available as podcasts """
|
||||||
|
return self.filter(Q(embed__isnull=False) | Q(is_public=True))
|
||||||
|
|
||||||
|
def diffusion(self, diffusion):
|
||||||
|
return self.filter(diffusion=diffusion)
|
||||||
|
|
||||||
|
|
||||||
class Sound(models.Model):
|
class Sound(models.Model):
|
||||||
"""
|
"""
|
||||||
A Sound is the representation of a sound file that can be either an excerpt
|
A Sound is the representation of a sound file that can be either an excerpt
|
||||||
|
@ -942,10 +931,10 @@ class Sound(models.Model):
|
||||||
help_text=_('program related to it'),
|
help_text=_('program related to it'),
|
||||||
)
|
)
|
||||||
diffusion = models.ForeignKey(
|
diffusion = models.ForeignKey(
|
||||||
'Diffusion',
|
Diffusion, models.SET_NULL,
|
||||||
verbose_name=_('diffusion'),
|
verbose_name=_('diffusion'),
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
on_delete=models.SET_NULL,
|
limit_choices_to={'initial__isnull': True},
|
||||||
help_text=_('initial diffusion related it')
|
help_text=_('initial diffusion related it')
|
||||||
)
|
)
|
||||||
type = models.SmallIntegerField(
|
type = models.SmallIntegerField(
|
||||||
|
@ -980,17 +969,19 @@ class Sound(models.Model):
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
help_text=_('last modification date and time'),
|
help_text=_('last modification date and time'),
|
||||||
)
|
)
|
||||||
good_quality = models.NullBooleanField(
|
is_good_quality = models.BooleanField(
|
||||||
_('good quality'),
|
_('good quality'),
|
||||||
help_text=_('sound\'s quality is okay'),
|
help_text=_('sound meets quality requirements for diffusion'),
|
||||||
blank=True, null=True
|
blank=True, null=True
|
||||||
)
|
)
|
||||||
public = models.BooleanField(
|
is_public = models.BooleanField(
|
||||||
_('public'),
|
_('public'),
|
||||||
default=False,
|
default=False,
|
||||||
help_text=_('the sound is accessible to the public')
|
help_text=_('the sound is accessible to the public')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
objects = SoundQuerySet.as_manager()
|
||||||
|
|
||||||
def get_mtime(self):
|
def get_mtime(self):
|
||||||
"""
|
"""
|
||||||
Get the last modification date from file
|
Get the last modification date from file
|
||||||
|
@ -1080,7 +1071,7 @@ class Sound(models.Model):
|
||||||
|
|
||||||
if self.mtime != mtime:
|
if self.mtime != mtime:
|
||||||
self.mtime = mtime
|
self.mtime = mtime
|
||||||
self.good_quality = None
|
self.is_good_quality = None
|
||||||
logger.info('sound %s: m_time has changed. Reset quality info',
|
logger.info('sound %s: m_time has changed. Reset quality info',
|
||||||
self.path)
|
self.path)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,12 @@ $body-background-color: $light;
|
||||||
|
|
||||||
/** page **/
|
/** page **/
|
||||||
.page {
|
.page {
|
||||||
.header {
|
& > .cover {
|
||||||
|
float: right;
|
||||||
|
max-width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .header {
|
||||||
margin-bottom: 1.5em;
|
margin-bottom: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,10 @@ class Page(StatusModel):
|
||||||
|
|
||||||
objects = PageQueryset.as_manager()
|
objects = PageQueryset.as_manager()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_published(self):
|
||||||
|
return self.status == self.STATUS.published
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
return reverse(self.detail_url_name, kwargs={'slug': self.slug})
|
return reverse(self.detail_url_name, kwargs={'slug': self.slug})
|
||||||
|
|
|
@ -7165,7 +7165,11 @@ label.panel-block {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/** page **/
|
/** page **/
|
||||||
.page .header {
|
.page > .cover {
|
||||||
|
float: right;
|
||||||
|
max-width: 45%; }
|
||||||
|
|
||||||
|
.page > .header {
|
||||||
margin-bottom: 1.5em; }
|
margin-bottom: 1.5em; }
|
||||||
|
|
||||||
.page .headline {
|
.page .headline {
|
||||||
|
|
|
@ -41,25 +41,35 @@ Context:
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns">
|
<div class="columns is-desktop">
|
||||||
<main class="column page">
|
<main class="column page">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<h1 class="title is-1">{% block title %}{% endblock %}</h1>
|
<h1 class="title is-1">{% block title %}{% endblock %}</h1>
|
||||||
|
|
||||||
|
{% if parent %}
|
||||||
|
<h4 class="subtitle is-size-3">
|
||||||
|
<a href="{{ parent.path }}">
|
||||||
|
❬ {{ parent.title }}</a></li>
|
||||||
|
</h4>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{% block main %}{% endblock main %}
|
{% block main %}{% endblock main %}
|
||||||
</main>
|
</main>
|
||||||
<aside class="column is-one-third">
|
{% if nav_side %}
|
||||||
{% block side_nav %}
|
<aside class="column is-one-third-desktop">
|
||||||
{% block cover %}
|
{% block cover %}
|
||||||
{% if cover is not None %}
|
{% if cover is not None %}
|
||||||
<img class="cover" src="{{ cover.url }}" class="cover"/>
|
<img class="cover" src="{{ cover.url }}" class="cover"/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block side_nav %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</aside>
|
</aside>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,27 +18,27 @@ Context variables:
|
||||||
class="small-cover">
|
class="small-cover">
|
||||||
</div>
|
</div>
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
<div>
|
<h5 class="subtitle is-size-5">
|
||||||
<h5 class="subtitle is-size-5 is-inline-block">
|
{% if d_page %}
|
||||||
{% if d_page %}
|
<a href="{{ d_page.path }}">{{ d_page.title }}</a>
|
||||||
<a href="{{ d_page.path }}">{{ d_page.title }}</a>
|
{% endif %}
|
||||||
{% endif %}
|
</h5>
|
||||||
|
|
||||||
{% if not page or p_page != page %}
|
<div class="">
|
||||||
{% if d_page %} — {% endif %}
|
{% if not page or p_page != page %}
|
||||||
{% if p_page %}
|
{% if p_page %}
|
||||||
<a href="{{ p_page.path }}" class="has-text-grey-dark">
|
<a href="{{ p_page.path }}" class="has-text-grey-dark">
|
||||||
{{ p_page.title }}</a>
|
{{ p_page.title }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ program.name }}
|
{{ program.name }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% if not hide_schedule %} — {% endif %}
|
||||||
</h5>
|
{% endif %}
|
||||||
|
|
||||||
{% if not hide_schedule %}
|
{% if not hide_schedule %}
|
||||||
<time datetime="{{ object.start|date:"c" }}" title="{{ object.start }}"
|
<time datetime="{{ object.start|date:"c" }}" title="{{ object.start }}"
|
||||||
class="has-text-weight-light is-size-6">
|
class="has-text-weight-light is-size-6">
|
||||||
— {{ object.start|date:"d M, H:i" }}
|
{{ object.start|date:"d M, H:i" }}
|
||||||
</time>
|
</time>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
14
aircox_web/templates/aircox_web/diffusion_page.html
Normal file
14
aircox_web/templates/aircox_web/diffusion_page.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends "aircox_web/program_base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
{% if podcasts %}
|
||||||
|
{% for object in podcasts %}
|
||||||
|
{% include "aircox_web/podcast_item.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endwith %}
|
||||||
|
|
|
@ -12,18 +12,8 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% if program %}
|
|
||||||
<h4 class="subtitle is-size-3">
|
|
||||||
<a href="{% url "program-page" slug=program.slug %}">❬ {{ program.name }}</a></li>
|
|
||||||
</h4>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="section">
|
<section>
|
||||||
{% for object in object_list %}
|
{% for object in object_list %}
|
||||||
{% include "aircox_web/diffusion_item.html" %}
|
{% include "aircox_web/diffusion_item.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -27,10 +27,4 @@ Context:
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block side_nav %}
|
|
||||||
{% if cover is not None %}
|
|
||||||
<img class="cover" src="{{ cover.url }}" class="cover"/>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
aircox_web/templates/aircox_web/podcast_item.html
Normal file
8
aircox_web/templates/aircox_web/podcast_item.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="podcast">
|
||||||
|
{% if object.embed %}
|
||||||
|
{{ object.embed }}
|
||||||
|
{% else %}
|
||||||
|
<audio src="{{ object.url }}" controls>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
29
aircox_web/templates/aircox_web/program_base.html
Normal file
29
aircox_web/templates/aircox_web/program_base.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "aircox_web/page.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block side_nav %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
{% if diffusions %}
|
||||||
|
<section>
|
||||||
|
<h4 class="subtitle is-size-4">{% trans "Last shows" %}</h4>
|
||||||
|
|
||||||
|
{% for object in diffusions %}
|
||||||
|
{% include "aircox_web/diffusion_item.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<nav class="pagination is-centered">
|
||||||
|
<ul class="pagination-list">
|
||||||
|
<li>
|
||||||
|
<a href="{% url "diffusion-list" program_slug=page.slug %}"
|
||||||
|
class="pagination-link"
|
||||||
|
aria-label="{% trans "Show all diffusions" %}">
|
||||||
|
{% trans "All diffusions" %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -1,38 +1,8 @@
|
||||||
{% extends "aircox_web/page.html" %}
|
{% extends "aircox_web/program_base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% with page.program as program %}
|
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{% include "aircox_web/program_header.html" %}
|
{% include "aircox_web/program_header.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block side_nav %}
|
|
||||||
{{ block.super }}
|
|
||||||
|
|
||||||
{% if diffusions %}
|
|
||||||
<section>
|
|
||||||
<h4 class="subtitle is-size-4">{% trans "Last shows" %}</h4>
|
|
||||||
|
|
||||||
{% for object in diffusions %}
|
|
||||||
{% include "aircox_web/diffusion_item.html" %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<nav class="pagination is-centered">
|
|
||||||
<ul class="pagination-list">
|
|
||||||
<li>
|
|
||||||
<a href="{% url "diffusion-list" program_slug=page.slug %}"
|
|
||||||
class="pagination-link"
|
|
||||||
aria-label="{% trans "Show all diffusions" %}">
|
|
||||||
{% trans "All diffusions" %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from collections import OrderedDict, deque
|
from collections import OrderedDict, deque
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.db.models import Q
|
from django.http import Http404
|
||||||
from django.core.paginator import Paginator
|
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import TemplateView, DetailView, ListView
|
from django.views.generic import DetailView, ListView
|
||||||
from django.views.generic.base import TemplateResponseMixin, ContextMixin
|
from django.views.generic.base import TemplateResponseMixin, ContextMixin
|
||||||
|
|
||||||
from content_editor.contents import contents_for_item
|
from content_editor.contents import contents_for_item
|
||||||
|
@ -36,9 +35,14 @@ def route_page(request, path=None, *args, model=None, site=None, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
class BaseView(TemplateResponseMixin, ContextMixin):
|
class BaseView(TemplateResponseMixin, ContextMixin):
|
||||||
title = None
|
|
||||||
cover = None
|
|
||||||
site = None
|
site = None
|
||||||
|
""" Current website """
|
||||||
|
nav_side = False
|
||||||
|
""" Show side navigation """
|
||||||
|
title = None
|
||||||
|
""" Page title """
|
||||||
|
cover = None
|
||||||
|
""" Page cover """
|
||||||
|
|
||||||
def dispatch(self, request, *args, site=None, **kwargs):
|
def dispatch(self, request, *args, site=None, **kwargs):
|
||||||
self.site = site if site is not None else \
|
self.site = site if site is not None else \
|
||||||
|
@ -53,6 +57,7 @@ class BaseView(TemplateResponseMixin, ContextMixin):
|
||||||
|
|
||||||
kwargs.setdefault('site', self.site)
|
kwargs.setdefault('site', self.site)
|
||||||
kwargs.setdefault('cover', self.cover)
|
kwargs.setdefault('cover', self.cover)
|
||||||
|
kwargs.setdefault('nav_side', self.nav_side)
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,31 +84,52 @@ class PageView(BaseView, DetailView):
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ProgramPageView(PageView):
|
class BaseProgramView(PageView):
|
||||||
""" Base view class for pages. """
|
""" Base view class for programs and their sub-pages. """
|
||||||
|
nav_side = True
|
||||||
|
list_count=5
|
||||||
|
|
||||||
|
def get_diffusions_queryset(self, program, queryset=None):
|
||||||
|
qs = get_diffusions_with_page() if queryset is None else queryset
|
||||||
|
return qs.before().filter(program=program).order_by('-start')
|
||||||
|
|
||||||
|
def get_context_data(self, program, **kwargs):
|
||||||
|
if not hasattr(program, 'page') or not program.page.is_published:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
if 'diffusions' not in kwargs:
|
||||||
|
diffs = self.get_diffusions_queryset(program)[:self.list_count]
|
||||||
|
kwargs['diffusions'] = diffs
|
||||||
|
return super().get_context_data(program=program, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ProgramPageView(BaseProgramView):
|
||||||
template_name = 'aircox_web/program_page.html'
|
template_name = 'aircox_web/program_page.html'
|
||||||
model = ProgramPage
|
model = ProgramPage
|
||||||
|
|
||||||
list_count=10
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().select_related('program')
|
return super().get_queryset().select_related('program')
|
||||||
|
|
||||||
def get_context_data(self, program=None, diffusions=None, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
program = program or self.object.program
|
kwargs.setdefault('program', self.object.program)
|
||||||
diffusions = diffusions or \
|
return super().get_context_data(**kwargs)
|
||||||
get_diffusions_with_page().filter(program=program)
|
|
||||||
return super().get_context_data(
|
|
||||||
program=program,
|
|
||||||
diffusions=diffusions.order_by('-start')[:self.list_count],
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DiffusionPageView(PageView):
|
class DiffusionPageView(BaseProgramView):
|
||||||
# template_name = 'aircox_web/diffusion.html'
|
template_name = 'aircox_web/program_base.html'
|
||||||
model = DiffusionPage
|
model = DiffusionPage
|
||||||
|
|
||||||
|
def get_podcasts(self, diffusion):
|
||||||
|
return aircox.Sound.objects.diffusion(diffusion).podcasts()
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
diffusion = self.object.diffusion
|
||||||
|
kwargs.setdefault('program', diffusion.program)
|
||||||
|
kwargs.setdefault('parent', getattr(kwargs['program'], 'page', None))
|
||||||
|
if not 'podcasts' in kwargs:
|
||||||
|
kwargs['podcasts'] = self.get_podcasts(diffusion)
|
||||||
|
print('get prodcasts...', kwargs['podcasts'], diffusion)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
# TODO: pagination: in template, only a limited number of pages displayed
|
# TODO: pagination: in template, only a limited number of pages displayed
|
||||||
|
@ -133,7 +159,7 @@ class DiffusionsView(BaseView, ListView):
|
||||||
program = kwargs.setdefault('program', self.program)
|
program = kwargs.setdefault('program', self.program)
|
||||||
if program is not None and hasattr(program, 'page'):
|
if program is not None and hasattr(program, 'page'):
|
||||||
kwargs.setdefault('cover', program.page.cover)
|
kwargs.setdefault('cover', program.page.cover)
|
||||||
kwargs.setdefault('page', program.page)
|
kwargs.setdefault('parent', program.page)
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user