forked from rc/aircox
cfr #121 Co-authored-by: Christophe Siraut <d@tobald.eu.org> Co-authored-by: bkfox <thomas bkfox net> Co-authored-by: Thomas Kairos <thomas@bkfox.net> Reviewed-on: rc/aircox#131 Co-authored-by: Chris Tactic <ctactic@noreply.git.radiocampus.be> Co-committed-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
This commit is contained in:
@@ -1,55 +1,65 @@
|
||||
import os
|
||||
|
||||
from django.conf import settings as d_settings
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from easy_thumbnails.files import get_thumbnailer
|
||||
|
||||
from aircox.conf import settings
|
||||
|
||||
from .page import Page
|
||||
from .page import ChildPage
|
||||
from .program import ProgramChildQuerySet
|
||||
from .sound import Sound
|
||||
|
||||
__all__ = ("Episode",)
|
||||
|
||||
|
||||
class Episode(Page):
|
||||
objects = ProgramChildQuerySet.as_manager()
|
||||
class EpisodeQuerySet(ProgramChildQuerySet):
|
||||
def with_podcasts(self):
|
||||
return self.filter(episodesound__sound__is_public=True).distinct()
|
||||
|
||||
|
||||
class Episode(ChildPage):
|
||||
objects = EpisodeQuerySet.as_manager()
|
||||
detail_url_name = "episode-detail"
|
||||
item_template_name = "aircox/widgets/episode_item.html"
|
||||
list_url_name = "episode-list"
|
||||
edit_url_name = "episode-edit"
|
||||
template_prefix = "episode"
|
||||
|
||||
@property
|
||||
def program(self):
|
||||
return getattr(self.parent, "program", None)
|
||||
|
||||
@cached_property
|
||||
def podcasts(self):
|
||||
"""Return serialized data about podcasts."""
|
||||
from ..serializers import PodcastSerializer
|
||||
|
||||
podcasts = [PodcastSerializer(s).data for s in self.sound_set.public().order_by("type")]
|
||||
if self.cover:
|
||||
options = {"size": (128, 128), "crop": "scale"}
|
||||
cover = get_thumbnailer(self.cover).get_thumbnail(options).url
|
||||
else:
|
||||
cover = None
|
||||
|
||||
for index, podcast in enumerate(podcasts):
|
||||
podcasts[index]["cover"] = cover
|
||||
podcasts[index]["page_url"] = self.get_absolute_url()
|
||||
podcasts[index]["page_title"] = self.title
|
||||
return podcasts
|
||||
return self.parent_subclass
|
||||
|
||||
@program.setter
|
||||
def program(self, value):
|
||||
self.parent = value
|
||||
|
||||
@cached_property
|
||||
def podcasts(self):
|
||||
"""Return serialized data about podcasts."""
|
||||
query = self.episodesound_set.all().public().order_by("-broadcast", "position")
|
||||
return self._to_podcasts(query)
|
||||
|
||||
@cached_property
|
||||
def sounds(self):
|
||||
"""Return serialized data about all related sounds."""
|
||||
query = self.episodesound_set.all().order_by("-broadcast", "position")
|
||||
return self._to_podcasts(query)
|
||||
|
||||
def _to_podcasts(self, query):
|
||||
from ..serializers import EpisodeSoundSerializer as serializer_class
|
||||
|
||||
query = query.select_related("sound")
|
||||
podcasts = [serializer_class(s).data for s in query]
|
||||
for index, podcast in enumerate(podcasts):
|
||||
podcasts[index]["page_url"] = self.get_absolute_url()
|
||||
podcasts[index]["page_title"] = self.title
|
||||
return podcasts
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Episode")
|
||||
verbose_name_plural = _("Episodes")
|
||||
|
||||
def get_absolute_url(self):
|
||||
if not self.is_published:
|
||||
return self.program.get_absolute_url()
|
||||
return super().get_absolute_url()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.parent is None:
|
||||
raise ValueError("missing parent program")
|
||||
@@ -74,3 +84,54 @@ class Episode(Page):
|
||||
else title
|
||||
)
|
||||
return super().get_init_kwargs_from(page, title=title, program=page, **kwargs)
|
||||
|
||||
|
||||
class EpisodeSoundQuerySet(models.QuerySet):
|
||||
def episode(self, episode):
|
||||
if isinstance(episode, int):
|
||||
return self.filter(episode_id=episode)
|
||||
return self.filter(episode=episode)
|
||||
|
||||
def available(self):
|
||||
return self.filter(sound__is_removed=False)
|
||||
|
||||
def public(self):
|
||||
return self.filter(sound__is_public=True)
|
||||
|
||||
def broadcast(self):
|
||||
return self.available().filter(broadcast=True)
|
||||
|
||||
def playlist(self, order="position"):
|
||||
# TODO: subquery expression
|
||||
if order:
|
||||
self = self.order_by(order)
|
||||
query = self.filter(sound__file__isnull=False, sound__is_removed=False).values_list("sound__file", flat=True)
|
||||
return [os.path.join(d_settings.MEDIA_ROOT, file) for file in query]
|
||||
|
||||
|
||||
class EpisodeSound(models.Model):
|
||||
"""Element of an episode playlist."""
|
||||
|
||||
episode = models.ForeignKey(Episode, on_delete=models.CASCADE)
|
||||
sound = models.ForeignKey(Sound, on_delete=models.CASCADE)
|
||||
position = models.PositiveSmallIntegerField(
|
||||
_("order"),
|
||||
default=0,
|
||||
help_text=_("position in the playlist"),
|
||||
)
|
||||
broadcast = models.BooleanField(
|
||||
_("Broadcast"),
|
||||
blank=None,
|
||||
help_text=_("The sound is broadcasted on air"),
|
||||
)
|
||||
|
||||
objects = EpisodeSoundQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Podcast")
|
||||
verbose_name_plural = _("Podcasts")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.broadcast is None:
|
||||
self.broadcast = self.sound.broadcast
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
Reference in New Issue
Block a user