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
21 class SoundCell(CellBase):
22 soundfile = models.ForeignKey('emissions.SoundFile', null=True)
25 verbose_name = _('Sound')
27 def render(self, context):
28 tmpl = template.loader.get_template('panikombo/audio.html')
29 context['soundfile'] = self.soundfile
30 return tmpl.render(context)
32 def get_default_form_class(self):
33 from .forms import SoundCellForm
36 def get_included_items(self):
37 if not self.soundfile:
39 return [self.soundfile.episode]
41 def get_additional_label(self):
43 if self.soundfile.fragment:
44 return u'%s - %s - %s' % (
45 self.soundfile.episode.emission.title,
46 self.soundfile.episode.title,
50 self.soundfile.episode.emission.title,
51 self.soundfile.episode.title)
57 class EpisodeCell(CellBase):
58 episode = models.ForeignKey('emissions.Episode', null=True)
61 verbose_name = _('Episode')
63 def render(self, context):
64 tmpl = template.loader.get_template('panikombo/episode.html')
65 context['episode'] = self.episode
67 context['soundfile'] = self.episode.main_sound
68 return tmpl.render(context)
70 def get_included_items(self):
75 def get_default_form_class(self):
76 from .forms import EpisodeCellForm
77 return EpisodeCellForm
79 def get_additional_label(self):
82 self.episode.emission.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,
100 choices=((0, _('All')),
104 template_name = 'panikombo/episode_auto_selection.html'
108 verbose_name = _('Automatic Episode Selection')
110 def get_included_items(self):
111 episodes_queryset = Episode.objects.select_related()
113 episodes_queryset = episodes_queryset.filter(emission__categories__in=[self.category.id])
114 if self.tags.count():
115 episodes_queryset = episodes_queryset.filter(tags__in=self.tags.all())
117 and_tags = get_parsed_tags(self.and_tags)
118 episodes_queryset = episodes_queryset.filter(tags__in=and_tags)
121 episodes_queryset = episodes_queryset.extra(
122 select={ 'first_diffusion': 'emissions_diffusion.datetime', },
123 select_params=(False, True),
124 where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
125 WHERE episode_id = emissions_episode.id)'''],
126 tables=['emissions_diffusion'])
127 episodes_queryset = episodes_queryset.order_by('first_diffusion').distinct()
128 elif self.period == 1:
129 episodes_queryset = episodes_queryset.extra(
130 select={ 'first_diffusion': 'emissions_diffusion.datetime', },
131 select_params=(False, True),
132 where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
133 WHERE episode_id = emissions_episode.id) AND
134 datetime >= CURRENT_TIMESTAMP'''],
135 tables=['emissions_diffusion'])
136 episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
137 elif self.period == 2:
138 episodes_queryset = episodes_queryset.extra(
139 select={ 'first_diffusion': 'emissions_diffusion.datetime', },
140 select_params=(False, True),
141 where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
142 WHERE episode_id = emissions_episode.id) AND
143 datetime < CURRENT_TIMESTAMP'''],
144 tables=['emissions_diffusion'])
145 episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
147 return episodes_queryset
149 def get_cell_extra_context(self, context):
150 ctx = super(EpisodeAutoSelectionCell, self).get_cell_extra_context(context)
151 ctx['title'] = self.title
153 if (self.category or self.period or self.tags.count()):
154 ctx['episodes'] = self.get_included_items()
160 def get_default_form_class(self):
161 from .forms import EpisodeAutoSelectionCellForm
162 return EpisodeAutoSelectionCellForm
164 def get_additional_label(self):
170 class NewsItemAutoSelectionCell(CellBase):
171 title = models.CharField(_('Title'), max_length=50, blank=True)
172 tags = TaggableManager(_('Tags'), blank=True)
173 and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
174 future = models.BooleanField(_('Future Events Only'), default=True)
175 category = models.ForeignKey('emissions.NewsCategory',
176 verbose_name=_('Category'), null=True, blank=True)
178 template_name = 'panikombo/newsitem_auto_selection.html'
181 verbose_name = _('Automatic Newsitem Selection')
183 def get_included_items(self):
184 newsitems_queryset = NewsItem.objects.select_related()
185 if self.tags.count():
186 newsitems_queryset = newsitems_queryset.filter(tags__in=self.tags.all())
188 and_tags = get_parsed_tags(self.and_tags)
189 newsitems_queryset = newsitems_queryset.filter(tags__in=and_tags)
191 newsitems_queryset = newsitems_queryset.filter(event_date__gte=date.today())
193 newsitems_queryset = newsitems_queryset.filter(category=self.category)
194 newsitems_queryset = newsitems_queryset.order_by('-event_date', '-creation_timestamp')
195 return newsitems_queryset
197 def get_cell_extra_context(self, context):
198 ctx = super(NewsItemAutoSelectionCell, self).get_cell_extra_context(context)
199 ctx['title'] = self.title
201 if self.tags.count() or self.future or self.category:
202 ctx['newsitems'] = self.get_included_items()
204 ctx['newsitems'] = []
208 def get_default_form_class(self):
209 from .forms import NewsItemAutoSelectionCellForm
210 return NewsItemAutoSelectionCellForm
212 def get_additional_label(self):
218 class ItemTopik(models.Model):
219 newsitem = models.ForeignKey('emissions.NewsItem', verbose_name=_('News Item'),
220 null=True, blank=True)
221 episode = models.ForeignKey('emissions.Episode', verbose_name=_('Episode'),
222 null=True, blank=True)
223 page = models.ForeignKey('data.Page', null=True, blank=True)
227 class SoundsCell(CellBase):
228 title = models.CharField(_('Title'), max_length=150, blank=True)
229 include_search_input = models.BooleanField(_('Include search input'), default=True)
230 include_fragments = models.BooleanField(_('Include fragments'), default=True)
231 limit_to_focus = models.BooleanField(_('Limit to focused elements'), default=False)
232 sound_format = models.ForeignKey('emissions.Format',
233 verbose_name=_('Limit to format'), null=True, blank=True)
234 minimal_duration = models.PositiveIntegerField(
235 _('Minimal duration (in minutes)'),
236 default=None, blank=True, null=True)
237 maximal_duration = models.PositiveIntegerField(
238 _('Maximal duration (in minutes)'),
239 default=None, blank=True, null=True)
240 count = models.PositiveSmallIntegerField(_('Count'), default=20)
241 sort_order = models.CharField(_('Sort order'), default='-creation_timestamp',
244 ('-creation_timestamp', _('Reverse chronological (creation)')),
245 ('-first_diffusion', _('Reverse chronological (diffusion)')),
246 ('creation_timestamp', _('Chronological (creation)')),
247 ('first_diffusion', _('Chronological (diffusion)')),
253 verbose_name = _('Sounds')
255 def get_cell_extra_context(self, context):
256 soundfiles = SoundFile.objects.prefetch_related('episode__emission__categories')
257 soundfiles = soundfiles.filter(podcastable=True)
258 if not self.include_fragments:
259 soundfiles = soundfiles.filter(fragment=False)
260 if self.limit_to_focus:
261 soundfiles = soundfiles.filter(got_focus__isnull=False)
262 if self.sound_format:
263 soundfiles = soundfiles.filter(format_id=self.sound_format_id)
264 if self.minimal_duration:
265 soundfiles = soundfiles.filter(duration__gte=self.minimal_duration * 60)
266 if self.maximal_duration:
267 soundfiles = soundfiles.filter(duration__lte=self.maximal_duration * 60)
268 soundfiles = soundfiles.select_related().extra(
269 select={'first_diffusion': 'emissions_diffusion.datetime', },
270 select_params=(False, True),
271 where=['''datetime = (SELECT MIN(datetime)
272 FROM emissions_diffusion
273 WHERE episode_id = emissions_episode.id)'''],
274 tables=['emissions_diffusion'],).order_by(self.sort_order).distinct()
276 'include_search_input': self.include_search_input,
277 'soundfiles': soundfiles[:self.count],