#132 | #121: backoffice / dev-1.0-121 (#131)

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:
2024-04-28 22:02:09 +02:00
committed by Thomas Kairos
parent 1e17a1334a
commit 55123c386d
348 changed files with 124397 additions and 17879 deletions

View File

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