aircox-radiocampus/aircox/views/episode.py

179 lines
5.8 KiB
Python

from django.contrib.auth.mixins import UserPassesTestMixin
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.generic.base import View
from aircox.models import Episode, Program, StaticPage, Track
from aircox import forms, filters, permissions
from .mixins import VueFormDataMixin
from .page import attach, PageDetailView, PageListView, PageUpdateView
__all__ = (
"EpisodeDetailView",
"EpisodeListView",
"PodcastListView",
"EpisodeCreateView",
"EpisodeUpdateView",
)
class EpisodeDetailView(PageDetailView):
model = Episode
def can_edit(self, obj):
return permissions.program.can(self.request.user, "update", obj)
def get_context_data(self, **kwargs):
if "tracks" not in kwargs:
kwargs["tracks"] = self.object.track_set.order_by("position")
return super().get_context_data(**kwargs)
def get_related_queryset(self):
return (
self.get_queryset().parent(self.object.parent).exclude(pk=self.object.pk).published().order_by("-pub_date")
)
def get_related_url(self):
return reverse("episode-list", kwargs={"parent_slug": self.object.parent.slug})
def get(self, *args, **kwargs):
"""When episode is unpublished and user not authorized, redirect to
parent page."""
try:
self.object = super().get_object()
except Http404:
episode = get_object_or_404(Episode, slug=self.kwargs["slug"])
return HttpResponseRedirect(reverse("program-detail", kwargs={"slug": episode.program.slug}))
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
@attach
class EpisodeListView(PageListView):
model = Episode
filterset_class = filters.EpisodeFilters
parent_model = Program
attach_to_value = StaticPage.Target.EPISODES
@attach
class PodcastListView(EpisodeListView):
attach_to_value = StaticPage.Target.PODCASTS
queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
class EpisodeUpdateView(UserPassesTestMixin, VueFormDataMixin, PageUpdateView):
model = Episode
form_class = forms.EpisodeForm
template_name = "aircox/episode_form.html"
def get_form_kwargs(self, *args, **kwargs):
"""Render selected attribute on option 0."""
fk = super().get_form_kwargs(*args, **kwargs)
if not fk["instance"].status:
fk["initial"]["status"] = "0"
return fk
def can_edit(self, obj):
return self.test_func()
def test_func(self):
obj = self.get_object()
return permissions.program.can(self.request.user, "update", obj)
def get_tracklist_queryset(self, episode):
return Track.objects.filter(episode=episode).order_by("position")
def get_tracklist_formset(self, episode, **kwargs):
kwargs.update(
{
"prefix": "tracks",
"queryset": self.get_tracklist_queryset(episode),
"initial": [
{
"episode": episode.id,
}
],
}
)
return forms.TrackFormSet(**kwargs)
def get_soundlist_queryset(self, episode):
return episode.episodesound_set.all().select_related("sound").order_by("position")
def get_soundlist_formset(self, episode, **kwargs):
kwargs.update(
{
"prefix": "sounds",
"queryset": self.get_soundlist_queryset(episode),
"initial": [
{
"episode": episode.id,
}
],
}
)
return forms.EpisodeSoundFormSet(**kwargs)
def get_sound_form(self, episode, **kwargs):
kwargs.update(
{
"initial": {
"program": episode.parent_id,
"name": episode.title,
"is_public": True,
},
}
)
return forms.SoundCreateForm(**kwargs)
def get_context_data(self, **kwargs):
forms = (
("soundlist_formset", self.get_soundlist_formset),
("tracklist_formset", self.get_tracklist_formset),
("sound_form", self.get_sound_form),
)
for key, func in forms:
if key not in kwargs:
kwargs[key] = func(self.object)
for key in ("soundlist_formset", "tracklist_formset"):
formset = kwargs[key]
kwargs[f"{key}_data"] = self.get_formset_data(formset, {"episode": self.object.id})
return super().get_context_data(**kwargs)
def post(self, request, *args, **kwargs):
resp = super().post(request, *args, **kwargs)
formsets = {
"soundlist_formset": self.get_soundlist_formset(self.object, data=request.POST),
"tracklist_formset": self.get_tracklist_formset(self.object, data=request.POST),
}
invalid = False
for formset in formsets.values():
if not formset.is_valid():
invalid = True
else:
formset.save()
if invalid:
return self.get(request, **formsets)
return resp
class EpisodeCreateView(UserPassesTestMixin, View):
def get(self, request, **kwargs):
program = self.get_object()
episode = Episode.objects.create(program=program, title="%s (%s)" % (program.title, _("draft")))
return HttpResponseRedirect(reverse("episode-edit", kwargs={"pk": episode.pk}))
def test_func(self):
program = self.get_object()
return permissions.program.can(self.request.user, "update", program)
def get_object(self):
return get_object_or_404(Program, pk=self.kwargs["pk"])