1 from datetime import date
4 from django import template
5 from django.db import models
6 from django.db.models.functions import Lower
7 from django.utils.encoding import force_text, python_2_unicode_compatible
8 from django.utils.translation import ugettext_lazy as _
10 from ckeditor.fields import RichTextField
11 from taggit.models import Tag
12 from taggit.managers import TaggableManager
13 from taggit.utils import parse_tags
15 from combo.data.models import CellBase
16 from combo.data.library import register_cell_class
18 from emissions.models import Episode, NewsItem, SoundFile
22 class SoundCell(CellBase):
23 soundfile = models.ForeignKey('emissions.SoundFile', null=True)
26 verbose_name = _('Sound')
28 def render(self, context):
29 tmpl = template.loader.get_template('panikombo/audio.html')
30 context['soundfile'] = self.soundfile
31 return tmpl.render(context)
33 def get_default_form_class(self):
34 from .forms import SoundCellForm
38 def get_included_items(self):
39 if not self.soundfile:
41 return [self.soundfile.episode]
43 def get_additional_label(self):
45 if self.soundfile.fragment:
46 return u'%s - %s - %s' % (
47 self.soundfile.episode.emission.title,
48 self.soundfile.episode.title,
52 return u'%s - %s' % (self.soundfile.episode.emission.title, self.soundfile.episode.title)
58 class EpisodeCell(CellBase):
59 episode = models.ForeignKey('emissions.Episode', null=True)
62 verbose_name = _('Episode')
64 def render(self, context):
65 tmpl = template.loader.get_template('panikombo/episode.html')
66 context['episode'] = self.episode
68 context['soundfile'] = self.episode.main_sound
69 return tmpl.render(context)
71 def get_included_items(self):
76 def get_default_form_class(self):
77 from .forms import EpisodeCellForm
79 return EpisodeCellForm
81 def get_additional_label(self):
83 return u'%s - %s' % (self.episode.emission.title, self.episode.title)
87 def get_parsed_tags(tagstring):
88 tags = parse_tags(tagstring)
89 return [x for x in Tag.objects.filter(name__in=tags)]
93 class EpisodeAutoSelectionCell(CellBase):
94 title = models.CharField(_('Title'), max_length=50, blank=True)
95 tags = TaggableManager(_('Tags'), blank=True)
96 and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
97 category = models.ForeignKey('emissions.Category', null=True, blank=True)
98 period = models.PositiveSmallIntegerField(
99 _('Period'), default=0, choices=((0, _('All')), (1, _('Future')), (2, _('Past')))
102 template_name = 'panikombo/episode_auto_selection.html'
105 verbose_name = _('Automatic Episode Selection')
107 def get_included_items(self):
108 episodes_queryset = Episode.objects.select_related()
110 episodes_queryset = episodes_queryset.filter(emission__categories__in=[self.category.id])
111 if self.tags.count():
112 episodes_queryset = episodes_queryset.filter(tags__in=self.tags.all())
114 and_tags = get_parsed_tags(self.and_tags)
115 episodes_queryset = episodes_queryset.filter(tags__in=and_tags)
118 episodes_queryset = episodes_queryset.extra(
120 'first_diffusion': 'emissions_diffusion.datetime',
122 select_params=(False, True),
124 '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
125 WHERE episode_id = emissions_episode.id)'''
127 tables=['emissions_diffusion'],
129 episodes_queryset = episodes_queryset.order_by('first_diffusion').distinct()
130 elif self.period == 1:
131 episodes_queryset = episodes_queryset.extra(
133 'first_diffusion': 'emissions_diffusion.datetime',
135 select_params=(False, True),
137 '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
138 WHERE episode_id = emissions_episode.id) AND
139 datetime >= CURRENT_TIMESTAMP'''
141 tables=['emissions_diffusion'],
143 episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
144 elif self.period == 2:
145 episodes_queryset = episodes_queryset.extra(
147 'first_diffusion': 'emissions_diffusion.datetime',
149 select_params=(False, True),
151 '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
152 WHERE episode_id = emissions_episode.id) AND
153 datetime < CURRENT_TIMESTAMP'''
155 tables=['emissions_diffusion'],
157 episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
159 return episodes_queryset
161 def get_cell_extra_context(self, context):
162 ctx = super(EpisodeAutoSelectionCell, self).get_cell_extra_context(context)
163 ctx['title'] = self.title
165 if self.category or self.period or self.tags.count():
166 ctx['episodes'] = self.get_included_items()
172 def get_default_form_class(self):
173 from .forms import EpisodeAutoSelectionCellForm
175 return EpisodeAutoSelectionCellForm
177 def get_additional_label(self):
184 class NewsItemAutoSelectionCell(CellBase):
185 title = models.CharField(_('Title'), max_length=50, blank=True)
186 tags = TaggableManager(_('Tags'), blank=True)
187 and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
188 future = models.BooleanField(_('Future Events Only'), default=True)
189 category = models.ForeignKey('emissions.NewsCategory', verbose_name=_('Category'), null=True, blank=True)
191 template_name = 'panikombo/newsitem_auto_selection.html'
194 verbose_name = _('Automatic Newsitem Selection')
196 def get_included_items(self):
197 newsitems_queryset = NewsItem.objects.select_related()
198 if self.tags.count():
199 newsitems_queryset = newsitems_queryset.filter(tags__in=self.tags.all())
201 and_tags = get_parsed_tags(self.and_tags)
202 newsitems_queryset = newsitems_queryset.filter(tags__in=and_tags)
204 newsitems_queryset = newsitems_queryset.filter(event_date__gte=date.today())
206 newsitems_queryset = newsitems_queryset.filter(category=self.category)
207 newsitems_queryset = newsitems_queryset.order_by('-event_date', '-creation_timestamp')
208 return newsitems_queryset
210 def get_cell_extra_context(self, context):
211 ctx = super(NewsItemAutoSelectionCell, self).get_cell_extra_context(context)
212 ctx['title'] = self.title
214 if self.tags.count() or self.future or self.category:
215 ctx['newsitems'] = self.get_included_items()
217 ctx['newsitems'] = []
221 def get_default_form_class(self):
222 from .forms import NewsItemAutoSelectionCellForm
224 return NewsItemAutoSelectionCellForm
226 def get_additional_label(self):
232 class ItemTopik(models.Model):
233 newsitem = models.ForeignKey('emissions.NewsItem', verbose_name=_('News Item'), null=True, blank=True)
234 episode = models.ForeignKey('emissions.Episode', verbose_name=_('Episode'), null=True, blank=True)
235 page = models.ForeignKey('data.Page', null=True, blank=True)
239 class SoundsCell(CellBase):
240 title = models.CharField(_('Title'), max_length=150, blank=True)
241 include_search_input = models.BooleanField(_('Include search input'), default=True)
242 include_fragments = models.BooleanField(_('Include fragments'), default=True)
243 limit_to_focus = models.BooleanField(_('Limit to focused elements'), default=False)
244 sound_format = models.ForeignKey(
245 'emissions.Format', verbose_name=_('Limit to format'), null=True, blank=True
247 tags = TaggableManager(_('Tags'), blank=True)
248 minimal_duration = models.PositiveIntegerField(
249 _('Minimal duration (in minutes)'), default=None, blank=True, null=True
251 maximal_duration = models.PositiveIntegerField(
252 _('Maximal duration (in minutes)'), default=None, blank=True, null=True
254 count = models.PositiveSmallIntegerField(_('Count'), default=20)
255 sort_order = models.CharField(
257 default='-creation_timestamp',
260 ('-creation_timestamp', _('Reverse chronological (creation)')),
261 ('-first_diffusion', _('Reverse chronological (diffusion)')),
262 ('creation_timestamp', _('Chronological (creation)')),
263 ('first_diffusion', _('Chronological (diffusion)')),
269 verbose_name = _('Sounds')
271 def get_default_form_fields(self):
272 fields = super().get_default_form_fields()
273 fields.insert(fields.index('minimal_duration'), 'tags')
276 def get_cell_extra_context(self, context):
277 soundfiles = SoundFile.objects.prefetch_related('episode__emission__categories')
278 soundfiles = soundfiles.filter(podcastable=True)
279 if not self.include_fragments:
280 soundfiles = soundfiles.filter(fragment=False)
281 if self.limit_to_focus:
282 soundfiles = soundfiles.filter(got_focus__isnull=False)
283 if self.sound_format:
284 soundfiles = soundfiles.filter(format_id=self.sound_format_id)
285 if self.minimal_duration:
286 soundfiles = soundfiles.filter(duration__gte=self.minimal_duration * 60)
287 if self.maximal_duration:
288 soundfiles = soundfiles.filter(duration__lte=self.maximal_duration * 60)
289 if self.tags.exists():
290 soundfiles = soundfiles.filter(episode__tags__in=self.tags.all())
292 soundfiles.select_related()
295 'first_diffusion': 'emissions_diffusion.datetime',
297 select_params=(False, True),
299 '''datetime = (SELECT MIN(datetime)
300 FROM emissions_diffusion
301 WHERE episode_id = emissions_episode.id)'''
303 tables=['emissions_diffusion'],
305 .order_by(self.sort_order)
309 'include_search_input': self.include_search_input,
310 'soundfiles': soundfiles[: self.count],