8 from django import template
9 from django.conf import settings
10 from django.core.urlresolvers import reverse
11 from django.db.models.query import QuerySet
12 from django.utils.encoding import force_text
13 from django.utils.http import quote
14 from django.utils.six.moves.urllib import parse as urlparse
16 from datetime import datetime, timedelta
18 from emissions.models import Emission, Episode, NewsItem, SoundFile, Focus
19 from emissions.utils import period_program
21 from panikombo.models import Topik
23 from panikweb import utils
24 from panikweb import search
26 register = template.Library()
28 @register.filter(name='zip')
32 @register.inclusion_tag('includes/audio.html', takes_context=True)
33 def audio(context, sound=None, embed=False, display_fragment_name=False):
35 'episode': context.get('episode'),
37 'display_fragment_name': display_fragment_name,
41 @register.inclusion_tag('listen/nav.html', takes_context=True)
42 def listen_nav(context, date=None, klass=None):
45 'categories': context.get('categories'),
48 @register.inclusion_tag('news/nav.html', takes_context=True)
49 def news_nav(context, date=None, klass=None):
52 'newsitem': context.get('newsitem'),
53 'categories': context.get('categories'),
54 'news': context.get('news'),
55 'search_query': context.get('search_query'),
58 @register.inclusion_tag('emissions/nav.html', takes_context=True)
59 def emission_nav(context, date=None, klass=None):
62 'categories': context.get('categories'),
63 'episodes': context.get('episodes'),
64 'emission': context.get('emission'),
65 'episode': context.get('episode'),
66 'search_query': context.get('search_query'),
69 @register.inclusion_tag('episodes/inline.html', takes_context=True)
70 def episode_inline(context, date=None, model=None, klass=None):
73 'episode': context.get('episode'),
76 @register.inclusion_tag('episodes/resume.html', takes_context=True)
77 def episode_resume(context, date=None, model=None, klass=None):
81 'episode': context.get('episode'),
85 @register.inclusion_tag('episodes/detail.html', takes_context=True)
86 def episode_detail(context, date=None):
87 soundfiles = SoundFile.objects.select_related().filter(
88 fragment=True, podcastable=True, episode=context.get('episode'))
90 'episode': context.get('episode'),
91 'emission': context.get('emission'),
92 'diffusions': context.get('diffusions'),
93 'soundfiles': soundfiles,
95 'topiks': context.get('topiks'),
98 @register.inclusion_tag('emissions/detail.html', takes_context=True)
99 def emission_detail(context, date=None):
101 'emission': context.get('emission'),
102 'schedules': context.get('schedules'),
105 @register.inclusion_tag('emissions/resume.html', takes_context=True)
106 def emission_resume(context, date=None):
108 'emission': context.get('emission'),
109 'schedules': context.get('schedules'),
112 @register.inclusion_tag('emissions/inline.html', takes_context=True)
113 def emission_inline(context, date=None):
115 'emission': context.get('emission'),
116 'schedules': context.get('schedules'),
119 @register.inclusion_tag('soundfiles/resume.html')
120 def soundfile_resume(soundfile, date=None):
121 return {'soundfile': soundfile,
124 @register.inclusion_tag('includes/player.html', takes_context=True)
128 'unique': uuid.uuid4(),
129 'soundfiles': context.get('soundfiles'),
132 @register.inclusion_tag('includes/metaNav.html', takes_context=True)
133 def metanav(context):
135 request_path = context['request'].path
137 # a context without 'requests' may happen when rendering error pages
140 if request_path == '/':
142 elif request_path.startswith('/actus/'):
144 elif request_path.startswith('/sons/'):
146 elif request_path.startswith('/topiks'):
148 elif request_path.startswith('/emissions') or request_path == '/grille' or request_path == '/programme/':
149 section = 'Emissions'
150 elif request_path == '/recherche/':
153 'LANGUAGE_CODE': context.get('LANGUAGE_CODE'),
154 'sectionName': section,
157 @register.inclusion_tag('includes/week.html')
158 def weekview(year=None, week=None):
159 year = year if year else datetime.today().isocalendar()[0]
160 week = week if week else datetime.today().isocalendar()[1]
162 date = utils.tofirstdayinisoweek(year, week)
163 date = datetime(*date.timetuple()[:3])
165 program = period_program(date, date+timedelta(days=7))
168 days.append({'cells': [x for x in program if x.is_on_weekday(day+1)],
169 'datetime': date+timedelta(days=day)})
177 @register.inclusion_tag('includes/week-nav.html')
178 def weeknav(year=None, week=None, weekday=None):
179 year = year if year else datetime.today().isocalendar()[0]
180 week = week if week else datetime.today().isocalendar()[1]
181 weekday = weekday if weekday is not None else datetime.today().weekday()
183 date = utils.tofirstdayinisoweek(year, week)
184 date = datetime(*date.timetuple()[:3])
188 days.append({'datetime': date+timedelta(days=day)})
190 previous_week = date - timedelta(days=7)
191 previous_week_year, previous_week_no = previous_week.isocalendar()[:2]
193 next_week = date + timedelta(days=7)
194 next_week_year, next_week_no = next_week.isocalendar()[:2]
201 'previous_week_year': previous_week_year,
202 'previous_week_no': previous_week_no,
203 'next_week_year': next_week_year,
204 'next_week_no': next_week_no,
208 @register.inclusion_tag('news/inline.html', takes_context=True)
209 def news_inline(context, klass=None, logo=None):
211 'content': context.get('content'),
216 @register.inclusion_tag('news/roll.html')
219 'news': Focus.objects.filter(current=True).select_related('emission', 'newsitem',
220 'soundfile', 'episode', 'newsitem__category').order_by('?')[:3]
226 if isinstance(object, QuerySet):
227 return serialize('json', object)
228 return json.dumps(object)
231 def strreplace ( string, args ):
232 find = args.split(',')[0]
233 replace = args.split(',')[1]
234 return string.replace(find,replace)
237 def replace ( string, args ):
238 search = args.split(args[0])[1]
239 replace = args.split(args[0])[2]
241 return re.sub( search, replace, string )
244 def remove_facet(facet_id, url, facet):
245 scheme, netloc, path, query, fragment = list(urlparse.urlsplit(str(url)))
246 facet = '%s_exact:%s' % (facet_id, facet.encode('utf-8'))
247 query_string = urlparse.parse_qsl(query)
248 query_string = [x for x in query_string if not (
249 x[0] == 'selected_facets' and x[1] == facet)]
250 query = '&'.join(['%s=%s' % x for x in query_string])
251 url = urlparse.urlunsplit([scheme, netloc, path, query, None])
252 return force_text(re.sub(r'&page=\d+', '', url), 'utf-8')
255 def remove_tag_facet(url, facet):
256 return remove_facet('tags', url, facet)
259 def remove_category_facet(url, facet):
260 return remove_facet('categories', url, facet)
264 def remove_news_category_facet(url, facet):
265 return remove_facet('news_categories', url, facet)
268 def remove_format_facet(url, facet):
269 return remove_facet('format', url, facet)
272 def append_facet(facet_id, url, facet):
273 facet = quote(facet.encode('utf-8'), safe='')
276 return re.sub(r'&page=\d+', '', url + '&selected_facets=%s_exact:%s' % (facet_id, facet))
279 def append_tag_facet(url, facet):
280 return append_facet('tags', url, facet)
283 def append_category_facet(url, facet):
284 return append_facet('categories', url, facet)
287 def append_news_category_facet(url, facet):
288 return append_facet('news_categories', url, facet)
291 def append_format_facet(url, facet):
292 return append_facet('format', url, facet)
296 def search_result_template(parser, token):
298 tag_name, result_str = token.split_contents()
300 raise template.TemplateSyntaxError("%r tag requires exactly one argument" % token.contents.split()[0])
301 return FormatSearchResultNode(result_str)
304 class FormatSearchResultNode(template.Node):
305 def __init__(self, result_str):
306 self.result_var = template.Variable(result_str)
308 def render(self, context):
309 result = self.result_var.resolve(context)
312 'emission': 'emissions',
313 'episode': 'episodes'
315 t = template.loader.get_template('%s/search_result.html' % dir_mapping.get(result.model_name))
316 return t.render({'result': result})
319 @register.inclusion_tag('includes/piwik.html')
321 return {'enabled': settings.ENABLE_PIWIK}
325 def rfc822(datetime):
328 return email.utils.formatdate(time.mktime(datetime.timetuple()))
330 @register.inclusion_tag('includes/related.html', takes_context=False)
331 def related_objects(object):
332 sqs = search.MoreLikeThisSearchQuerySet().models(Emission, Episode, NewsItem)
333 return {'more_like_this': sqs.more_like_this(object)[:12]}
335 @register.inclusion_tag('includes/topik.html', takes_context=True)
336 def topik(context, topik):
337 return {'topik': topik}
340 def get_focus_url(object):
342 return reverse('newsitem-view', kwargs={'slug': object.newsitem.slug})
344 return reverse('emission-view', kwargs={'slug': object.emission.slug})
346 return reverse('episode-view', kwargs={
347 'slug': object.episode.slug, 'emission_slug': object.episode.emission.slug})
349 return reverse('episode-view', kwargs={
350 'slug': object.soundfile.episode.slug,
351 'emission_slug': object.soundfile.episode.emission.slug})
353 return object.page.get_online_url()
362 def image_file(page):
364 matching_topik = Topik.objects.get(page=page)
365 return matching_topik.image
366 except Topik.DoesNotExist:
372 def set_absolute_urls(text):
373 text = text.replace('src="/', 'src="%s' % settings.WEBSITE_BASE_URL)
374 text = text.replace('href="/', 'href="%s' % settings.WEBSITE_BASE_URL)
378 def as_absolute_url(url):
379 if url.startswith('/'):
380 url = settings.WEBSITE_BASE_URL + url.lstrip('/')