5 import newsletter.views
6 from combo.data.models import Page
7 from django.conf import settings
8 from django.contrib import messages
9 from django.contrib.auth.decorators import login_required
10 from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
11 from django.core.exceptions import PermissionDenied
12 from django.shortcuts import redirect
13 from django.template import loader
14 from django.urls import reverse
15 from django.views.generic.base import RedirectView, TemplateView
16 from django.views.generic.list import ListView
17 from emissions.models import Diffusion, Emission, Episode, Focus, NewsCategory, NewsItem, SoundFile
18 from emissions.utils import period_program
20 from .pige.views import PigeDownloadMixin
21 from .poll.models import Vote
22 from .service_messages.models import Message
24 logger = logging.getLogger('panikdb')
27 class Home(TemplateView, PigeDownloadMixin):
28 template_name = 'home.html'
30 def get_context_data(self, **kwargs):
31 context = super().get_context_data(**kwargs)
33 context.update(self.get_pige_context_data())
36 vote = Vote.objects.get(user=self.request.user)
37 except Vote.DoesNotExist:
38 context['display_poll_button'] = True
39 context['emissions'] = self.request.user.emissions.all().order_by('title')
40 context['news_categories'] = self.request.user.news_categories.all().order_by('title')
41 context['service_message'] = Message.objects.all().first()
42 if not context['service_message']:
43 context['service_message'] = Message.objects.create(style='info')
44 if not context['service_message'].text and not self.request.user.has_perm(
45 'service_messages.change_message'
47 context['service_message'] = None
48 if self.request.user.has_perm('emissions.add_focus'):
49 context['focused_items'] = Focus.objects.select_related().filter(current=True)
50 context['recent_episodes'] = Episode.objects.select_related().order_by('-last_update_timestamp')
51 context['recent_newsitems'] = NewsItem.objects.select_related().order_by('-last_update_timestamp')
52 context['recent_soundfiles'] = SoundFile.objects.select_related().order_by(
53 '-last_update_timestamp'
55 context['extra_top_links'] = settings.HOME_EXTRA_TOP_LINKS
60 home = login_required(Home.as_view())
63 class Search(TemplateView):
64 template_name = 'search/search.html'
66 def get_context_data(self, **kwargs):
67 context = super().get_context_data(**kwargs)
68 context['query'] = self.request.GET.get('q', '')
70 SearchVector('title', config=settings.FTS_DICTIONARY_CONFIG, weight='A')
71 + SearchVector('subtitle', config=settings.FTS_DICTIONARY_CONFIG, weight='A')
72 + SearchVector('text', config=settings.FTS_DICTIONARY_CONFIG, weight='B')
74 query = SearchQuery(self.request.GET.get('q', ''), config=settings.FTS_DICTIONARY_CONFIG)
76 'episodes': Episode.objects.annotate(rank=SearchRank(vector, query))
77 .filter(rank__gte=0.1)
78 .select_related('emission')
79 .order_by('-rank')[:10],
80 'emissions': Emission.objects.annotate(rank=SearchRank(vector, query))
81 .filter(rank__gte=0.1)
82 .order_by('-rank')[:10],
83 'newsitems': NewsItem.objects.annotate(rank=SearchRank(vector, query))
84 .filter(rank__gte=0.1)
85 .order_by('-rank')[:10],
90 search = Search.as_view()
93 class EmissionListView(emissions.views.EmissionListView):
97 emissions_list = login_required(EmissionListView.as_view())
100 class NewsListView(ListView):
103 def get_queryset(self):
104 return NewsCategory.objects.order_by('title')
106 def get_context_data(self, **kwargs):
107 context = super().get_context_data(**kwargs)
108 context['unsorted_newsitems'] = NewsItem.objects.filter(category__isnull=True).order_by('title')
112 news = login_required(NewsListView.as_view())
115 class NewsletterCreateView(newsletter.views.NewsletterCreateView):
116 def get_initial(self):
117 initial = super().get_initial()
119 newsletter_body = loader.get_template('newsletter/body.html')
120 newsletter_subject = loader.get_template('newsletter/subject.txt')
123 date = datetime.datetime.today()
124 if date.weekday() < 3:
125 # before and on Wednesday, use current week
126 date = date - datetime.timedelta(days=date.weekday())
128 # after Wednesday, use next week
129 date = date + datetime.timedelta(days=7 - date.weekday())
131 date = datetime.datetime(*date.timetuple()[:3])
132 date_end = date + datetime.timedelta(days=7)
134 context['date'] = date
135 context['date_end'] = date_end
137 context['soundfiles'] = (
138 SoundFile.objects.filter(podcastable=True, fragment=False)
140 .filter(creation_timestamp__gte=date - datetime.timedelta(days=7))
143 context['diffusions'] = list(
144 Diffusion.objects.select_related()
145 .filter(datetime__gte=date, datetime__lte=date + datetime.timedelta(days=7))
146 .order_by('datetime')
149 # remove rebroadcasts made during the same week
151 for diff in context['diffusions'][:]:
152 if diff.episode.id in seen_episodes:
153 context['diffusions'].remove(diff)
154 seen_episodes[diff.episode.id] = True
156 initial['subject'] = newsletter_subject.render(context)
157 initial['text'] = newsletter_body.render(context)
161 newsletter_create = NewsletterCreateView.as_view()
164 class FocusSetView(RedirectView):
167 def get_redirect_url(self, object_type, object_id):
168 if not self.request.user.has_perm('emissions.add_focus'):
169 raise PermissionDenied()
170 messages.success(self.request, emissions.views.SUCCESS_MESSAGE)
171 if object_type == 'emission':
172 emission = Emission.objects.get(id=object_id)
173 f, _created = Focus.objects.get_or_create(emission=emission)
176 logger.info('set focus on emission %s', emission)
177 return reverse('emission-view', kwargs={'slug': emission.slug})
178 if object_type == 'episode':
179 episode = Episode.objects.get(id=object_id)
180 f, _created = Focus.objects.get_or_create(episode=episode)
184 logger.info('set focus on episode %s', episode)
186 'episode-view', kwargs={'emission_slug': episode.emission.slug, 'slug': episode.slug}
188 if object_type == 'newsitem':
189 newsitem = NewsItem.objects.get(id=object_id)
190 f, _created = Focus.objects.get_or_create(newsitem=newsitem)
192 f.newsitem = newsitem
194 logger.info('set focus on newsitem %s', newsitem)
195 return reverse('newsitem-view', kwargs={'slug': newsitem.slug})
196 if object_type == 'soundfile':
197 soundfile = SoundFile.objects.get(id=object_id)
198 f, _created = Focus.objects.get_or_create(soundfile=soundfile)
200 f.soundfile = soundfile
202 logger.info('set focus on sound %s', soundfile)
206 'slug': soundfile.episode.slug,
207 'emission_slug': soundfile.episode.emission.slug,
210 if object_type == 'page':
211 page = Page.objects.get(id=object_id)
213 f = Focus.objects.get(page=page)
214 except Focus.DoesNotExist:
219 logger.info('set focus on page %s', page)
220 return reverse('combo-manager-page-view', kwargs={'pk': object_id})
223 focus_set = FocusSetView.as_view()
226 class FocusUnsetView(RedirectView):
229 def get_redirect_url(self, object_type, object_id):
230 if not self.request.user.has_perm('emissions.delete_focus'):
231 raise PermissionDenied()
232 messages.success(self.request, emissions.views.SUCCESS_MESSAGE)
233 if object_type == 'emission':
234 emission = Emission.objects.get(id=object_id)
235 focus = Focus.objects.get(emission=emission)
236 focus.current = False
238 logger.info('unset focus of emission %s', emission)
239 return reverse('emission-view', kwargs={'slug': emission.slug})
240 if object_type == 'episode':
241 episode = Episode.objects.get(id=object_id)
242 focus = Focus.objects.get(episode=episode)
243 focus.current = False
245 logger.info('unset focus of episode %s', episode)
247 'episode-view', kwargs={'emission_slug': episode.emission.slug, 'slug': episode.slug}
249 if object_type == 'newsitem':
250 newsitem = NewsItem.objects.get(id=object_id)
251 focus = Focus.objects.get(newsitem=newsitem)
252 focus.current = False
254 logger.info('unset focus of newsitem %s', newsitem)
255 return reverse('newsitem-view', kwargs={'slug': newsitem.slug})
256 if object_type == 'soundfile':
257 soundfile = SoundFile.objects.get(id=object_id)
258 focus = Focus.objects.get(soundfile=soundfile)
259 focus.current = False
261 logger.info('unset focus of soundfile %s', soundfile)
265 'slug': soundfile.episode.slug,
266 'emission_slug': soundfile.episode.emission.slug,
269 if object_type == 'page':
270 focus = Focus.objects.get(page=object_id)
271 focus.current = False
273 logger.info('unset focus of page %s', object_id)
274 return reverse('combo-manager-page-view', kwargs={'pk': object_id})
277 focus_unset = FocusUnsetView.as_view()