from django.contrib.auth.mixins import UserPassesTestMixin from django.http import 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}) @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"])