Commit a24403c0 authored by Simon Daron's avatar Simon Daron
Browse files

New files (archives)

parent 948f94f2
This diff is collapsed.
This diff is collapsed.
[{"pk": 1, "model": "fiber.contentitem", "fields": {"content_markup": "", "updated": "2013-08-25T15:59:12.480", "name": "", "created": "2013-08-24T01:00:04.303", "template_name": "", "used_on_pages_data": "[{\"url\": \"/la-radio/\", \"title\": \"La radio\"}]", "protected": false, "content_html": "<p>Radio Panik est une radio libre qui se d&eacute;finit comme radio associative d&rsquo;expression et de cr&eacute;ation et comme radio multi- et interculturelle. Elle a &eacute;t&eacute; cr&eacute;&eacute;e en 1983 &agrave; l&rsquo;initiative d&rsquo;un groupe de personnes militant contre le racisme et pour les droits de l&rsquo;homme.</p>\r\n\r\n<p>Leurs motivations, toujours actuelles, sont bien r&eacute;sum&eacute;es dans ses statuts&nbsp;:</p>\r\n\r\n<p><em>&quot;L&rsquo;objet de l&rsquo;association est de contribuer - avant tout par le moyen de la radiodiffusion - &agrave; la promotion socioculturelle de la population dans la r&eacute;gion bruxelloise. Elle a comme but l&rsquo;&eacute;mancipation r&eacute;elle des individus dans le respect des diff&eacute;rences culturelles et des proc&eacute;dures d&eacute;mocratiques.&quot;</em></p>\r\n\r\n<p>Radio Panik a donc fait partie de cette premi&egrave;re g&eacute;n&eacute;ration de radios libres consid&eacute;r&eacute;es comme &quot; engag&eacute;es &quot; pour leur action militante en faveur d&rsquo;une approche critique de l&rsquo;information. Si son investissement au niveau local, tant au niveau social que culturel, s&rsquo;est peu &agrave; peu impos&eacute; comme l&rsquo;un de ses objectifs prioritaires, elle n&rsquo;a jamais perdu de vue cette mission &quot; g&eacute;n&eacute;raliste &quot; et demeure, au sein d&rsquo;un paysage m&eacute;diatique de plus en plus uniforme, un outil de communication dont la position marginale favorise la libert&eacute;, l&rsquo;ind&eacute;pendance et la diversit&eacute;.</p>\r\n\r\n<p>Ayant occup&eacute; successivement plusieurs adresses &agrave; Saint-Josse et &agrave; Schaerbeek, Radio Panik a su concilier actualit&eacute; locale et internationale, information et cr&eacute;ation, en ouvrant aux diverses communaut&eacute;s qui font de Bruxelles un v&eacute;ritable carrefour culturel, un espace &quot;sans fronti&egrave;res&quot;, ouvert &agrave; l&rsquo;expression de &quot;voix parall&egrave;les&quot; qui invitent &agrave; entendre, entre les ondes, un autre son de cloche.</p>\r\n\r\n<p>Aujourd&rsquo;hui, Radio Panik est soutenue par le Minist&egrave;re de la Communaut&eacute; fran&ccedil;aise depuis 2006, et depuis 2011 reconnue en tant qu&rsquo;association d&rsquo;&Eacute;ducation Permanente. Depuis 2008 elle b&eacute;n&eacute;ficie &eacute;galement du statut de &quot;radio associative et d&rsquo;expression &agrave; vocation culturelle ou d&rsquo;&eacute;ducation permanente&quot;.</p>\r\n\r\n<p>Direction g&eacute;n&eacute;rale de la Culture&nbsp;:&nbsp;<a href=\"http://www.culture.be/\" rel=\"external\">http://www.culture.be</a></p>\r\n\r\n<p>Service de l&rsquo;Education permanente&nbsp;:&nbsp;<a href=\"http://www.educationpermanente.cfwb.be/\" rel=\"external\">http://www.educationpermanente.cfwb.be</a></p>\r\n", "metadata": null}}, {"pk": 2, "model": "fiber.contentitem", "fields": {"content_markup": "", "updated": "2013-08-25T15:58:15.178", "name": "", "created": "2013-08-25T15:58:14.006", "template_name": "", "used_on_pages_data": "[{\"url\": \"/la-redaction/\", \"title\": \"La r\\u00e9daction\"}]", "protected": false, "content_html": "<p><span style=\"color: rgb(0, 0, 0); font-family: Verdana, Geneva, Sans, sans-serif; font-size: 12px; line-height: 16.796875px;\">Vous pouvez participer &agrave; la r&eacute;daction de panik, tous les jours de la semaine, de 19 &agrave; 20h30. La R&eacute;daction se rencontre r&eacute;guli&egrave;rement pour... Les th&eacute;matiques, c&rsquo;est ceci cel&agrave;, etc.</span></p>\r\n", "metadata": null}}, {"pk": 3, "model": "fiber.contentitem", "fields": {"content_markup": "", "updated": "2013-08-25T15:58:29.080", "name": "", "created": "2013-08-25T15:58:28.104", "template_name": "", "used_on_pages_data": "[{\"url\": \"/la-redaction/l-equipe/\", \"title\": \"L'\\u00e9quipe\"}]", "protected": false, "content_html": "<p>Bla bla bla.</p>\r\n", "metadata": null}}, {"pk": 4, "model": "fiber.contentitem", "fields": {"content_markup": "", "updated": "2013-08-25T16:00:26.627", "name": "", "created": "2013-08-25T16:00:25.660", "template_name": "", "used_on_pages_data": "[{\"url\": \"/la-radio/charte/\", \"title\": \"Charte\"}]", "protected": false, "content_html": "<div id=\"wysiwyg\">\r\n<div>\r\n<div dir=\"ltr\">\r\n<h3>Radio Panik est une radio libre</h3>\r\n\r\n<p>Elle ne poursuit aucun but lucratif. Elle ne se soumet pas au contr&ocirc;le direct ou indirect de soci&eacute;t&eacute;s d&rsquo;int&eacute;r&ecirc;ts &eacute;conomiques, commerciaux et financiers. Les ressources en provenance du sponsoring et de la publicit&eacute; doivent rester subordonn&eacute;es par rapport &agrave; d&rsquo;autres types de ressources. Elles ne peuvent avoir aucune influence sur la conception et le contenu de la programmation. Radio Panik ne peut se subordonner en aucune fa&ccedil;on ni &agrave; un parti politique, ni &agrave; un syndicat, ni aux mandataires publics. Radio Panik se comprend comme un p&ocirc;le particulier dans le tissu associatif.</p>\r\n\r\n<h3>Radio Panik est une radio d&rsquo;expression et de cr&eacute;ation</h3>\r\n\r\n<p>Elle ne veut pas imiter ou reproduire en petit ce qui se fait dans les radios priv&eacute;es commerciales ou dans les radios &eacute;manation d&rsquo;une seule institution ou d&rsquo;un seul groupe. Au contraire, elle a la vocation de rechercher une programmation alternative, d&eacute;centralis&eacute;e et originale par rapport &agrave; celle des radios-entreprises ou des radios pousse-disques. Elle favorise particuli&egrave;rement les essais de cr&eacute;ation radiophonique. L&rsquo;information y constitue un &eacute;l&eacute;ment essentiel.</p>\r\n\r\n<h3>Radio Panik est une radio communautaire</h3>\r\n\r\n<p>Elle est une radio communautaire au sens o&ugrave; les auditeurs sont per&ccedil;us non comme des consommateurs d&rsquo;id&eacute;es re&ccedil;ues et des productions de l&rsquo;industrie culturelle, mais comme des individus intelligents et actifs, eux-m&ecirc;mes aptes &agrave; l&rsquo;expression et &agrave; la cr&eacute;ation. Radio Panik n&rsquo;est pas une radio de professionnels, mais fait profession de comp&eacute;tence, rigueur et exigence pour que l&rsquo;outil soit utilis&eacute; le plus qualitativement possible.</p>\r\n\r\n<h3>Radio Panik est une radio urbaine</h3>\r\n\r\n<p>Elle se comprend comme une radio de la r&eacute;gion bruxelloise et revendique au niveau institutionnel le type de reconnaissance et le type de fr&eacute;quence n&eacute;cessaires pour pouvoir couvrir la r&eacute;gion. Elle se veut reflet et agent actif des vibrations sociales et culturelles dans le contexte urbain bruxellois. Elle se veut vecteur de progr&egrave;s social et d&rsquo;&eacute;mancipation des individus. Elle met en avant le respect des droits de l&rsquo;homme et des valeurs d&eacute;mocratiques dans la recherche d&rsquo;une soci&eacute;t&eacute; plus humaine et plus juste. Dans la recherche d&rsquo;un environnement urbain qui sauvegarde les richesses naturelles et favorise les possibilit&eacute;s de rencontres multiples et de convivialit&eacute; joyeuse entre les habitants, Radio PANIK se veut un facteur de d&eacute;pollution des ondes. C&rsquo;est en ce sens que Radio PANIK veut faire oeuvre d&rsquo;information et d&rsquo;&eacute;ducation permanente. Elle entend en particulier &ecirc;tre active pour &eacute;viter le d&eacute;veloppement de la ville en soci&eacute;t&eacute; duale et pour contrecarrer les m&eacute;canismes d&rsquo;exclusion sociale. Elle ouvre ses portes aux porteurs d&rsquo;expression des cat&eacute;gories d&eacute;favoris&eacute;es, celles-l&agrave; m&ecirc;me qui ont moins que d&rsquo;autres la possibilit&eacute; d&rsquo;acc&egrave;s aux m&eacute;dias.</p>\r\n\r\n<h3>Radio Panik est une radio interculturelle</h3>\r\n\r\n<p>Elle refuse autant les ghetto&iuml;sations et les int&eacute;grismes que l&rsquo;int&eacute;gration des cultures comprise comme assimilation au mod&egrave;le occidental dominant. Par ses diff&eacute;rentes &eacute;missions et r&eacute;alisations, Radio PANIK veut mettre en sc&egrave;ne la figure d&rsquo;une soci&eacute;t&eacute; o&ugrave; les approches et les &eacute;changes interculturels sont v&eacute;cus par les individus comme source de valeur et d&rsquo;&eacute;mancipation et non comme d&eacute;gradation ou fatalit&eacute;. Radio PANIK se tourne en particulier vers les jeunes g&eacute;n&eacute;rations ferment de la soci&eacute;t&eacute; interculturelle. Cet axe interculturel conduit Radio PANIK &agrave; une ouverture vers toutes les cultures du monde. Elle n&rsquo;oublie pas les conditionnements &eacute;conomiques, sociaux et politiques de l&rsquo;&eacute;mancipation des cultures dans le monde. M&ecirc;me si des &eacute;missions de communaut&eacute;s &eacute;trang&egrave;res dans leur langue sont admises, le fran&ccedil;ais sera la langue v&eacute;hiculaire dominante.</p>\r\n\r\n<h3>Radio Panik est une radio associative</h3>\r\n\r\n<p>Radio PANIK est une association d&rsquo;individus et de groupes r&eacute;unis pour r&eacute;aliser ensemble les objectifs de la station. Les projets d&rsquo;&eacute;missions et de r&eacute;alisations doivent correspondre &agrave; la raison sociale de la radio. Les personnes actives &agrave; Radio PANIK veilleront &agrave; ce que la pluralit&eacute; des &eacute;missions soit non un obstacle, mais une chance par rapport &agrave; la solidarit&eacute; interne et par rapport &agrave; la r&eacute;alisation de la raison sociale. L&rsquo;Assembl&eacute;e G&eacute;n&eacute;rale sera compos&eacute;e avant tout des artisans de la radio. C&rsquo;est elle qui &eacute;lit et r&eacute;voque le Conseil d&rsquo;Administration. Les responsables veilleront &agrave; favoriser les &eacute;changes et la concertation afin de cr&eacute;er une dynamique interne et d&rsquo;assurer le plus de transparence possible aux d&eacute;cisions. Afin de pr&eacute;ciser dans la clart&eacute; les droits et les devoirs des membres, afin aussi d&rsquo;&eacute;tablir les r&egrave;gles du jeu concernant le fonctionnement de l&rsquo;association, afin enfin de sauvegarder l&rsquo;outil, le Conseil d&rsquo;Administration r&eacute;dige un r&egrave;glement d&rsquo;ordre int&eacute;rieur approuv&eacute; par l&rsquo;Assembl&eacute;e G&eacute;n&eacute;rale.</p>\r\n\r\n<div>&nbsp;</div>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<div>&nbsp;</div>\r\n", "metadata": null}}, {"pk": 5, "model": "fiber.contentitem", "fields": {"content_markup": "", "updated": "2013-08-25T16:02:07.492", "name": "", "created": "2013-08-25T16:01:42.744", "template_name": "", "used_on_pages_data": "[{\"url\": \"/la-radio/membres/\", \"title\": \"Membres\"}]", "protected": false, "content_html": "<div id=\"wysiwyg\">\r\n<div dir=\"ltr\">\r\n<p>Liste des membres&nbsp;:&nbsp;<span style=\"line-height: 1.6em;\">Rebecca, Laura, Thelma &amp; Louise&nbsp;; Vincent, Fran&ccedil;ois, Paul et les autres&nbsp;!</span></p>\r\n\r\n<p>Vous l&rsquo;avez compris&nbsp;: contrairement &agrave; ce que semblait indiquer le lien que vous venez de cliquer, vous ne trouverez pas sur cette page la liste de nos membres, encore moins leur adresse, profession, nationalit&eacute; ou type de chocolat pr&eacute;f&eacute;r&eacute;. Radio Panik est, depuis sa naissance en 1983, tant le creuset que la chambre d&rsquo;&eacute;cho de luttes sociales et d&rsquo;actions revendicatives. Nos antennes font office de rendez-vous militants o&ugrave; se croisent tant&ocirc;t des r&eacute;fugi&eacute;s politiques pr&eacute;sents sur notre territoire tant&ocirc;t des acteurs associatifs locaux ou globaux et souvent tous en m&ecirc;me temps dans un incessant malstrom de discours &eacute;nerv&eacute;s et de propositions alternatives. En d&rsquo;autres termes, Radio Panik n&rsquo;est pas seulement soucieuse de l&rsquo;effectivit&eacute; de la libert&eacute; de conscience, de parole et d&rsquo;association&nbsp;; ce triptyque libertaire est au coeur de notre action, il est notre raison d&rsquo;&ecirc;tre... a fortiori dans un contexte de fichage g&eacute;n&eacute;ralis&eacute; et de criminalisation larv&eacute;e des forces vives les plus remuantes. Il nous semblerait d&egrave;s lors id&eacute;ologiquement inconcevable de livrer aux p&acirc;tures virtuellement inconnues l&rsquo;identit&eacute; et les coordonn&eacute;es de personnes qui nous sont concr&egrave;tement si proches.</p>\r\n\r\n<p>Enfin, et d&rsquo;un point de vue strictement juridique, il serait largement douteux de publier les donn&eacute;es personnelles concernant nos membres. En effet, les articles 5, a. et 6 &sect; 1er et &sect; 2&egrave;me de la loi du 8 d&eacute;cembre 1992 relative &agrave; la protection de la vie priv&eacute;e &agrave; l&rsquo;&eacute;gard des traitements de donn&eacute;es &agrave; caract&egrave;re personnel interdisent formellement tout traitement, a fortiori d&rsquo;informations prot&eacute;g&eacute;es (telle la qualit&eacute; de membre d&rsquo;une association) sans l&rsquo;accord indubitable et expr&egrave;s des personnes concern&eacute;es, accord qu&rsquo;en l&rsquo;esp&egrave;ce celles-ci ne nous ont pas donn&eacute; et que nous ne leur avons pas demand&eacute;.</p>\r\n\r\n<p>Bref, vous voulez conna&icirc;tre nos membres&nbsp;? &Eacute;coutez nos &eacute;missions&nbsp;!</p>\r\n</div>\r\n</div>\r\n", "metadata": null}}, {"pk": 1, "model": "fiber.page", "fields": {"meta_description": "", "rght": 14, "updated": "2013-08-25T15:54:42.511", "level": 0, "parent": null, "title": "main-menu", "url": "main-menu", "template_name": "tpl-default.html", "created": "2013-08-24T00:54:36.816", "mark_current_regexes": "", "redirect_page": null, "lft": 1, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 2, "model": "fiber.page", "fields": {"meta_description": "", "rght": 9, "updated": "2013-08-24T00:55:20.155", "level": 1, "parent": 1, "title": "La radio", "url": "la-radio", "template_name": "tpl-default.html", "created": "2013-08-24T00:55:20.155", "mark_current_regexes": "", "redirect_page": null, "lft": 2, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 3, "model": "fiber.page", "fields": {"meta_description": "", "rght": 4, "updated": "2013-08-25T15:55:20.377", "level": 2, "parent": 2, "title": "Charte", "url": "charte", "template_name": "tpl-default.html", "created": "2013-08-25T15:55:20.377", "mark_current_regexes": "", "redirect_page": null, "lft": 3, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 4, "model": "fiber.page", "fields": {"meta_description": "", "rght": 6, "updated": "2013-08-25T15:55:28.782", "level": 2, "parent": 2, "title": "Statuts", "url": "statuts", "template_name": "tpl-default.html", "created": "2013-08-25T15:55:28.782", "mark_current_regexes": "", "redirect_page": null, "lft": 5, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 5, "model": "fiber.page", "fields": {"meta_description": "", "rght": 8, "updated": "2013-08-25T15:55:36.443", "level": 2, "parent": 2, "title": "Membres", "url": "membres", "template_name": "tpl-default.html", "created": "2013-08-25T15:55:36.443", "mark_current_regexes": "", "redirect_page": null, "lft": 7, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 6, "model": "fiber.page", "fields": {"meta_description": "", "rght": 13, "updated": "2013-08-25T15:56:01.395", "level": 1, "parent": 1, "title": "La r\u00e9daction", "url": "la-redaction", "template_name": "tpl-default.html", "created": "2013-08-25T15:56:01.395", "mark_current_regexes": "", "redirect_page": null, "lft": 10, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 7, "model": "fiber.page", "fields": {"meta_description": "", "rght": 12, "updated": "2013-08-25T15:56:16.482", "level": 2, "parent": 6, "title": "L'\u00e9quipe", "url": "l-equipe", "template_name": "tpl-default.html", "created": "2013-08-25T15:56:16.482", "mark_current_regexes": "", "redirect_page": null, "lft": 11, "protected": false, "tree_id": 1, "is_public": true, "show_in_menu": true, "metadata": null}}, {"pk": 1, "model": "fiber.pagecontentitem", "fields": {"sort": 0, "block_name": "main", "content_item": 1, "page": 2}}, {"pk": 2, "model": "fiber.pagecontentitem", "fields": {"sort": 0, "block_name": "main", "content_item": 2, "page": 6}}, {"pk": 3, "model": "fiber.pagecontentitem", "fields": {"sort": 0, "block_name": "main", "content_item": 3, "page": 7}}, {"pk": 4, "model": "fiber.pagecontentitem", "fields": {"sort": 0, "block_name": "main", "content_item": 4, "page": 3}}, {"pk": 5, "model": "fiber.pagecontentitem", "fields": {"sort": 0, "block_name": "main", "content_item": 5, "page": 5}}]
\ No newline at end of file
This diff is collapsed.
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
'URL': 'http://test-web.radiopanik.org:8985/solr/panik'
},
}
import re
import urllib2
import uuid
from django import template
from django.db.models.query import QuerySet
register = template.Library()
@register.filter(name='zip')
def zip_lists(a, b):
return zip(a, b)
@register.inclusion_tag('includes/audio.html', takes_context=True)
def audio(context, sound=None):
return {
'episode': context.get('episode'),
'sound': sound
}
@register.inclusion_tag('episodes/resume.html', takes_context=True)
def episode_resume(context, date=None, model=None, klass=None):
return {
'model': model,
'class': klass,
'episode': context.get('episode'),
'date': date,
}
@register.inclusion_tag('emissions/detail.html', takes_context=True)
def emission_detail(context, date=None):
return {
'emission': context.get('emission'),
'schedules': context.get('schedules'),
}
@register.inclusion_tag('includes/player.html', takes_context=False)
def player():
return {'unique': uuid.uuid4()}
@register.inclusion_tag('includes/metaNav.html', takes_context=False)
def metanav():
return {}
@register.inclusion_tag('news/inline.html', takes_context=False)
def news_inline(content=None, klass=None, logo=None):
return {
'content': content,
'class': klass,
'logo': logo
}
@register.filter
def jsonify(object):
if isinstance(object, QuerySet):
return serialize('json', object)
return simplejson.dumps(object)
@register.filter
def remove_tag_facet(url, facet):
facet = urllib2.quote(facet.encode('utf-8'), safe='')
return re.sub(r'&page=\d+', '', url.replace('&selected_facets=tags_exact:%s' % facet, ''))
@register.filter
def remove_category_facet(url, facet):
facet = urllib2.quote(facet.encode('utf-8'), safe='')
return re.sub(r'&page=\d+', '', url.replace('&selected_facets=categories_exact:%s' % facet, ''))
@register.filter
def append_tag_facet(url, facet):
facet = urllib2.quote(facet.encode('utf-8'), safe='')
return re.sub(r'&page=\d+', '', url + '&selected_facets=tags_exact:%s' % facet)
@register.filter
def append_category_facet(url, facet):
facet = urllib2.quote(facet.encode('utf-8'), safe='')
return re.sub(r'&page=\d+', '', url + '&selected_facets=categories_exact:%s' % facet)
@register.tag
def search_result_template(parser, token):
try:
tag_name, result_str = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires exactly one argument" % token.contents.split()[0])
return FormatSearchResultNode(result_str)
class FormatSearchResultNode(template.Node):
def __init__(self, result_str):
self.result_var = template.Variable(result_str)
def render(self, context):
result = self.result_var.resolve(context)
dir_mapping = {
'newsitem': 'news',
'emission': 'emissions',
'episode': 'episodes'
}
t = template.loader.get_template('%s/search_result.html' % dir_mapping.get(result.model_name))
return t.render(template.context.Context({'result': result}, autoescape=context.autoescape))
# initiated from http://djangosnippets.org/snippets/2145/
import os
import re
from PIL import Image
from django.db.models.signals import post_save, pre_delete
from django.template import Library
register = Library()
def thumbnail(image, size='100x100'):
# defining the size
x, y = [int(x) for x in size.split('x')]
# defining the filename and the miniature filename
filehead, filetail = os.path.split(image.path)
basename, format = os.path.splitext(filetail)
miniature = basename + '_' + size + format
filename = image.path
miniature_filename = os.path.join(filehead, miniature)
filehead, filetail = os.path.split(image.url)
miniature_url = filehead + '/' + miniature
if os.path.exists(miniature_filename) and \
os.path.getmtime(filename) > os.path.getmtime(miniature_filename):
os.unlink(miniature_filename)
# if the image wasn't already resized, resize it
if not os.path.exists(miniature_filename):
image = Image.open(filename)
if abs( (1.0*x/y) - (1.0*image.size[0]/image.size[1]) ) > 0.1:
# aspect ratio change, crop the image first
if image.size[0] > image.size[1]: # landscape
box = [0, 0, int(image.size[1] * (1.0*x/y)), image.size[1]]
box[0] = (image.size[0] - box[2]) / 2 # keep the middle
else:
box = [0, 0, image.size[0], int(image.size[0] * (1.0*x/y))]
box[1] = (image.size[1] - box[3]) / 4 # keep mostly the top
image = image.crop(box)
image = image.resize([x, y], Image.ANTIALIAS)
try:
image.save(miniature_filename, image.format, quality=90, optimize=1)
except:
image.save(miniature_filename, image.format, quality=90)
return miniature_url
register.filter(thumbnail)
def clean_thumb(sender, instance, **kwargs):
if not hasattr(instance, 'image'):
return
name, ext = os.path.splitext(os.path.basename(instance.image.name))
exp = '^%s_\d+x\d+x[0-1]{1}\%s' % (name, ext)
for file_path in os.listdir(settings.MEDIA_ROOT):
if re.search(exp, file_path):
os.unlink(settings.MEDIA_ROOT + file_path)
post_save.connect(clean_thumb)
pre_delete.connect(clean_thumb)
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.views.generic import RedirectView
from django.core.urlresolvers import reverse_lazy
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'panikweb.views.home', name='home'),
url(r'^onair.json$', 'panikweb.views.onair', name='onair'),
url(r'^program$', 'panikweb.views.program', name='program'),
url(r'^grid$', 'panikweb.views.grid', name='grid'),
url(r'^emissions/$', 'panikweb.views.emissions', name='emissions'),
url(r'^emissions/', include('emissions.urls')),
url(r'^ckeditor/', include('ckeditor.urls')),
url(r'^get$', 'panikweb.views.get', name='get'),
url(r'^listen$', 'panikweb.views.listen', name='listen'),
url(r'^news/$', 'panikweb.views.news', name='news'),
url(r'^news/(?P<slug>[\w,-]+)$', 'panikweb.views.newsitem', name='news-view'),
url(r'^search/', 'panikweb.search.view', name='search'),
(r'^api/v2/', include('fiber.rest_api.urls')),
(r'^admin/fiber/', include('fiber.admin_urls')),
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': ('fiber',),}),
url(r'^admin/', include(admin.site.urls)),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
)
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += patterns('',
(r'', 'fiber.views.page'),
)
try:
from local_urls import *
except ImportError, e:
pass
from datetime import datetime, timedelta
import math
from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.dates import _date_from_string
from jsonresponse import to_json
from emissions.models import Category, Emission, Episode, Diffusion, SoundFile, \
Schedule, Nonstop, NewsItem, NewsCategory
from emissions.utils import whatsonair, period_program
class ProgramView(TemplateView):
template_name = 'program.html'
def get_context_data(self, **kwargs):
context = super(ProgramView, self).get_context_data(**kwargs)
schedules = Schedule.objects.select_related().order_by('datetime')
days = []
for day in range(7):
days.append({'schedules': [x for x in schedules if x.is_on_weekday(day+1)],
'datetime': datetime(2007, 1, day+1)})
context['days'] = days
return context
program = ProgramView.as_view()
class ProgramWeekView(TemplateView):
template_name = 'week.html'
def get_context_data(self, year, week, **kwargs):
context = super(ProgramWeekView, self).get_context_data(**kwargs)
date = _date_from_string(year, '%Y', '1', '%w', week, '%W')
date = datetime(*date.timetuple()[:3])
program = period_program(date, date+timedelta(days=7))
days = []
for day in range(7):
days.append({'cells': [x for x in program if x.is_on_weekday(day+1)],
'datetime': date+timedelta(days=day)})
context['days'] = days
context['week'] = week
context['year'] = year
context['date'] = _date_from_string(year, '%Y', '1', '%w', week, '%W')
return context
week = ProgramWeekView.as_view()
class TimeCell:
nonstop = None
w = 1
h = 1
time_label = None
def __init__(self, i, j):
self.x = i
self.y = j
self.schedules = []
def add_schedule(self, schedule):
end_time = schedule.datetime + timedelta(
minutes=schedule.get_duration())
self.time_label = '%02d:%02d-%02d:%02d' % (
schedule.datetime.hour,
schedule.datetime.minute,
end_time.hour,
end_time.minute)
self.schedules.append(schedule)
def __unicode__(self):
if self.schedules:
return ', '.join([x.emission.title for x in self.schedules])
else:
return self.nonstop
def __eq__(self, other):
return (unicode(self) == unicode(other) and self.time_label == other.time_label)
class Grid(TemplateView):
template_name = 'grid.html'
def get_context_data(self, **kwargs):
context = super(Grid, self).get_context_data(**kwargs)
nb_lines = 2 * 24 # the cells are half hours
grid = []
times = ['%02d:%02d' % (x/2, x%2*30) for x in range(nb_lines)]
# start grid after the night programs
times = times[2*Schedule.DAY_HOUR_START:] + times[:2*Schedule.DAY_HOUR_START]
nonstops = []
for nonstop in Nonstop.objects.all():
if nonstop.start < nonstop.end:
nonstops.append([nonstop.start.hour + nonstop.start.minute/60.,
nonstop.end.hour + nonstop.end.minute/60.,
nonstop.title])
else:
# crossing midnight
nonstops.append([nonstop.start.hour + nonstop.start.minute/60.,
24,
nonstop.title])
nonstops.append([0,
nonstop.end.hour + nonstop.end.minute/60.,
nonstop.title])
nonstops.sort()
for i in range(nb_lines):
grid.append([])
for j in range(7):
grid[-1].append(TimeCell(i, j))
nonstop = [x for x in nonstops if i>=x[0]*2 and i<x[1]*2][0]
for time_cell in grid[-1]:
time_cell.nonstop = nonstop[2]
if nonstop[1] == 5:
# the one ending at 5am will be cut down, so we inscribe
# its duration manually
time_cell.time_label = '%02d:00-%02d:00' % (
nonstop[0], nonstop[1])
for schedule in Schedule.objects.select_related().order_by('datetime'):
row_start = schedule.datetime.hour * 2 + \
int(math.ceil(schedule.datetime.minute / 30))
day_no = schedule.get_weekday()
for step in range(int(math.ceil(schedule.get_duration() / 30.))):
if grid[(row_start+step)%nb_lines][day_no] is None:
grid[(row_start+step)%nb_lines][day_no] = TimeCell()
grid[(row_start+step)%nb_lines][day_no].add_schedule(schedule)
# start grid after the night programs
grid = grid[2*Schedule.DAY_HOUR_START:] + grid[:2*Schedule.DAY_HOUR_START]
# merge adjacent cells
# 1st thing is to merge cells on the same line, this will mostly catch
# consecutive nonstop cells
for i in range(nb_lines):
for j, cell in enumerate(grid[i]):
if grid[i][j] is None:
continue
t = 1
try:
# if the cells are identical, they are removed from the
# grid, and current cell width is increased
while grid[i][j+t] == cell:
cell.w += 1
grid[i][j+t] = None
t += 1
except IndexError:
pass
# once we're done we remove empty cells
grid[i] = [x for x in grid[i] if x is not None]
# 2nd thing is to merge cells vertically, this is emissions that last
# for more than 30 minutes
for i in range(nb_lines):
grid[i] = [x for x in grid[i] if x is not None]
for j, cell in enumerate(grid[i]):
if grid[i][j] is None:
continue
t = 1
try:
while True:
# we look if the next time cell has the same emissions
same_cell_below = [(bj, x) for bj, x in enumerate(grid[i+cell.h])
if x == cell and x.y == cell.y and x.w == cell.w]
if same_cell_below:
# if the cell was identical, we remove it and
# increase current cell height
bj, same_cell_below = same_cell_below[0]
del grid[i+cell.h][bj]
cell.h += 1
else:
# if the cell is different, we have a closer look
# to it, so we can remove emissions that will
# already be mentioned in the current cell.
#
# For example:
# - 7am30, seuls contre tout, 1h30
# - 8am, du pied gauche & la voix de la rue, 1h
# should produce: (this is case A)
# | 7:30-9:00 |
# | seuls contre tout |
# |---------------------|
# | 8:00-9:00 |
# | du pied gauche |
# | la voix de la rue |
#
# On the other hand, if all three emissions started
# at 7am30, we want: (this is case B)
# | 7:30-9:00 |
# | seuls contre tout |
# | du pied gauche |
# | la voix de la rue |
# that is we merge all of them, ignoring the fact
# that the other emissions will stop at 8am30
current_cell_schedules = set(grid[i][j].schedules)
cursor = 1
while True and current_cell_schedules:
same_cell_below = [x for x in grid[i+cursor] if x.y == grid[i][j].y]
if not same_cell_below:
cursor += 1
continue
same_cell_below = same_cell_below[0]
if current_cell_schedules.issubset(same_cell_below.schedules):
# this handles case A (see comment above)
for schedule in current_cell_schedules:
if schedule in same_cell_below.schedules:
same_cell_below.schedules.remove(schedule)
elif same_cell_below.schedules and \
current_cell_schedules.issuperset(same_cell_below.schedules):
# this handles case B (see comment above)
# we set the cell time label to the longest
# period
grid[i][j].time_label = same_cell_below.time_label
# then we sort emissions so the longest are
# put first
grid[i][j].schedules.sort(
lambda x, y: -cmp(x.get_duration(), y.get_duration()))
# then we add individual time labels to the
# other schedules
for schedule in current_cell_schedules:
if schedule not in same_cell_below.schedules:
end_time = schedule.datetime + timedelta(
minutes=schedule.get_duration())
schedule.time_label = '%02d:%02d-%02d:%02d' % (
schedule.datetime.hour,
schedule.datetime.minute,
end_time.hour,
end_time.minute)
grid[i][j].h += 1
grid[i+cursor].remove(same_cell_below)
cursor += 1
break
except IndexError:
pass
# cut night at 3am
grid = grid[:42]
times = times[:42]
context['grid'] = grid
context['times'] = times
context['categories'] = Category.objects.all()
context['weekdays'] = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi',
'Vendredi', 'Samedi', 'Dimanche']
return context
grid = Grid.as_view()
class Home(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super(Home, self).get_context_data(**kwargs)
context['newsImaged'] = list(NewsItem.objects.all().exclude(image__isnull=True).exclude(image__exact='').order_by('-datetime')[:3])
context['newsImaged2'] = list(NewsItem.objects.all().exclude(image__isnull=True).exclude(image__exact='').order_by('-datetime')[:10])
context['news'] = list(NewsItem.objects.all().order_by('-datetime')[:36])
context['emissions'] = list(Emission.objects.filter(archived=False).order_by('title'))
schedules = Schedule.objects.select_related().order_by('datetime')
days = []
for day in range(7):
days.append({'schedules': [x for x in schedules if x.is_on_weekday(day+1)],
'datetime': datetime(2007, 1, day+1)})
context['days'] = days
return context
home = Home.as_view()
class News(TemplateView):
template_name = 'news.html'
def get_context_data(self, **kwargs):
context = super(News, self).get_context_data(**kwargs)
context['newsImaged'] = list(NewsItem.objects.all().exclude(image__isnull=True).exclude(image__exact='').order_by('-datetime')[:3])
context['news'] = list(NewsItem.objects.all().order_by('-datetime')[:60])
context['categories'] = list(NewsCategory.objects.all())
return context
news = News.as_view()
class Emissions(TemplateView):
template_name = 'emissions.html'
def get_context_data(self, **kwargs):
context = super(Emissions, self).get_context_data(**kwargs)
context['emissions'] = Emission.objects.all().order_by('title')
return context
emissions = Emissions.as_view()
class Get(TemplateView):
template_name = 'get.html'
def get_context_data(self, **kwargs):
context = super(Get, self).get_context_data(**kwargs)
context['emissions'] = Emission.objects.all().order_by('title')
return context
get = Get.as_view()
class Listen(TemplateView):
template_name = 'listen.html'
def get_context_data(self, **kwargs):
context = super(Listen, self).get_context_data(**kwargs)
context['sounds'] = SoundFile.objects.all()[:15]
listenable = []
x=0
for episode in Episode.objects.all().extra(select={
'first_diffusion': 'emissions_diffusion.datetime',
},
select_params=(False, True),
where=['''datetime = (SELECT MIN(datetime)
FROM emissions_diffusion
WHERE episode_id = emissions_episode.id)'''],
tables=['emissions_diffusion'],
).order_by('-first_diffusion').reverse():
if x >= 24:
break
elif episode.has_sound is None:
continue
else:
x+=1
listenable .append(episode)
context['episodes'] = listenable
return context
listen = Listen.as_view()
@csrf_exempt
@to_json('api')
def onair(request):
d = whatsonair()
if d.get('episode'):
d['episode'] = {
'title': d['episode'].title,
'url': d['episode'].get_absolute_url()
}
if d.get('emission'):
d['emission'] = {
'title': d['emission'].title,
'url': d['emission'].get_absolute_url()
}