from django.core import validators
from django.db import models
-from ..emissions.models import Emission
+from emissions.models import Emission
class User(AbstractUser):
emissions = models.ManyToManyField(Emission)
+++ /dev/null
-from django.contrib import admin
-
-from .models import Emission, Episode, Category, Schedule, \
- SoundFile, NewsItem, NewsCategory, Nonstop
-
-class EmissionAdmin(admin.ModelAdmin):
- prepopulated_fields = {'slug': ('title',)}
-
-admin.site.register(Emission, EmissionAdmin)
-
-
-class EpisodeAdmin(admin.ModelAdmin):
- prepopulated_fields = {'slug': ('title',)}
-
-admin.site.register(Episode, EpisodeAdmin)
-
-
-class CategoryAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(Category, CategoryAdmin)
-
-
-class ScheduleAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(Schedule, ScheduleAdmin)
-
-
-class NewsCategoryAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(NewsCategory, NewsCategoryAdmin)
-
-
-class NewsItemAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(NewsItem, NewsItemAdmin)
-
-
-class SoundFileAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(SoundFile, SoundFileAdmin)
-
-
-class NonstopAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(Nonstop, NonstopAdmin)
+++ /dev/null
-[
- {
- "fields": {
- "end": "02:00:00",
- "start": "22:00:00",
- "title": "Biodiversit\u00e9"
- },
- "model": "emissions.nonstop",
- "pk": 1
- },
- {
- "fields": {
- "end": "05:00:00",
- "start": "02:00:00",
- "title": "R\u00eaveries"
- },
- "model": "emissions.nonstop",
- "pk": 2
- },
- {
- "fields": {
- "end": "07:30:00",
- "start": "05:00:00",
- "title": "La Panique"
- },
- "model": "emissions.nonstop",
- "pk": 3
- },
- {
- "fields": {
- "end": "10:00:00",
- "start": "07:30:00",
- "title": "Matin tranquille"
- },
- "model": "emissions.nonstop",
- "pk": 4
- },
- {
- "fields": {
- "end": "12:00:00",
- "start": "10:00:00",
- "title": "Up Beat Tempo"
- },
- "model": "emissions.nonstop",
- "pk": 5
- },
- {
- "fields": {
- "end": "13:00:00",
- "start": "12:00:00",
- "title": "L'heure de pointe"
- },
- "model": "emissions.nonstop",
- "pk": 6
- },
- {
- "fields": {
- "end": "16:00:00",
- "start": "13:00:00",
- "title": "Le Mange Disque"
- },
- "model": "emissions.nonstop",
- "pk": 7
- },
- {
- "fields": {
- "end": "19:00:00",
- "start": "16:00:00",
- "title": "Hop Bop and co"
- },
- "model": "emissions.nonstop",
- "pk": 8
- },
- {
- "fields": {
- "end": "22:00:00",
- "start": "19:00:00",
- "title": "Acouph\u00e8ne"
- },
- "model": "emissions.nonstop",
- "pk": 9
- }
-]
+++ /dev/null
-import datetime
-import re
-import unicodedata
-import os
-import uuid
-
-from django import forms
-from django.forms import fields
-
-from django.core.files.storage import DefaultStorage
-from django.core.urlresolvers import reverse
-from django.utils.safestring import mark_safe
-from django.conf import settings
-from django.template.loader import render_to_string
-
-from taggit.forms import TagWidget
-import datetimewidget.widgets
-
-from .models import Emission, Episode, Diffusion, Schedule, SoundFile
-
-
-DATETIME_OPTIONS = {
- 'format': 'dd/mm/yyyy hh:ii',
- 'language': 'fr',
- 'weekStart': '1',
- 'autoclose': 'true',
- }
-
-class DateTimeWidget(datetimewidget.widgets.DateTimeWidget):
- def __init__(self, *args, **kwargs):
- super(DateTimeWidget, self).__init__(*args, options=DATETIME_OPTIONS, **kwargs)
-
-
-def slugify(s):
- s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').lower()
- return re.sub(r'\W+', '-', s)
-
-
-class DayAndHourWidget(forms.MultiWidget):
- def __init__(self, attrs=None):
- WEEKDAYS = [u'Lundi', u'Mardi', u'Mercredi', u'Jeudi', u'Vendredi', u'Samedi', u'Dimanche']
- widgets = (
- forms.Select(attrs=attrs, choices=([(weekday, WEEKDAYS[weekday]) for weekday in range(7)])),
- forms.Select(attrs=attrs, choices=([(hour, hour) for hour in range(24)])),
- forms.Select(attrs=attrs, choices=([(minute, str(minute).zfill(2)) for minute in range(60)])),
- )
- super(DayAndHourWidget, self).__init__(widgets, attrs)
-
- def decompress(self, value):
- if value:
- return [value.weekday(), value.hour, value.minute]
- return [None, None, None]
-
- def value_from_datadict(self, data, files, name):
- # we only care about day/hour/minutes, but we conveniently use a
- # datetime value to store that; we pick 2007 as reference year as
- # it had its January 1st on a Monday.
- data_list = [
- widget.value_from_datadict(data, files, name + '_%s' % i)
- for i, widget in enumerate(self.widgets)]
-
- if data_list:
- return datetime.datetime(2007, 1, int(data_list[0])+1, int(data_list[1]), int(data_list[2]))
- return None
-
-
-class JqueryFileUploadFileInput(forms.FileInput):
- def render(self, name, value, attrs=None):
- output = render_to_string('emissions/upload.html', {
- 'upload_url': self.url,
- 'files': self.files,
- 'name': name,
- 'STATIC_URL': settings.STATIC_URL})
- return mark_safe(output)
-
-
-class JqueryFileUploadInput(forms.MultiWidget):
- needs_multipart_form = True
- upload_id_re = re.compile(r'^[a-z0-9A-Z-]+$')
- upload_id = None
-
- def __init__(self, attrs=None, choices=[], max_filename_length=None):
- self.max_filename_length = max_filename_length
- widget_list = (forms.HiddenInput(attrs=attrs),
- JqueryFileUploadFileInput(attrs=attrs))
- super(JqueryFileUploadInput, self).__init__(widget_list, attrs)
-
- def decompress(self, value):
- # map python value to widget contents
- if self.upload_id:
- pass
- elif isinstance(value, (list, tuple)) and value and value[0] is not None:
- self.upload_id = str(value[0])
- else:
- self.upload_id = str(uuid.uuid4())
- return [self.upload_id, None]
-
- def get_files_for_id(self, upload_id):
- storage = DefaultStorage()
- path = os.path.join('upload', upload_id)
- if not storage.exists(path):
- return
- for filepath in storage.listdir(path)[1]:
- name = os.path.basename(filepath)
- yield storage.open(os.path.join(path, name))
-
- def value_from_datadict(self, data, files, name):
- '''
- If some file was submitted, that's the value,
- If a regular hidden_id is present, use it to find uploaded files,
- otherwise return an empty list
- '''
- upload_id, file_input = super(JqueryFileUploadInput, self).value_from_datadict(data, files, name)
- if file_input:
- pass
- elif JqueryFileUploadInput.upload_id_re.match(upload_id):
- file_input = list(self.get_files_for_id(upload_id))
- else:
- file_input = []
- return file_input[0]
-
- def render(self, name, value, attrs=None):
- self.decompress(value)
- self.widgets[1].url = '/upload/%s/' % self.upload_id
- self.widgets[1].url = reverse('upload', kwargs={'transaction_id': self.upload_id})
- if self.max_filename_length:
- self.widgets[1].url += '?max_filename_length=%d' % self.max_filename_length
- self.widgets[1].files = '/upload/%s/' % self.get_files_for_id(self.upload_id)
- output = super(JqueryFileUploadInput, self).render(name, value,
- attrs)
- fileinput_id = '%s_%s' % (attrs['id'], '1')
- return output
-
-
-class EmissionForm(forms.ModelForm):
- class Meta:
- model = Emission
- exclude = ('slug',)
-
- def save(self, commit=True):
- if not self.instance.slug:
- self.instance.slug = slugify(self.instance.title)
- return super(EmissionForm, self).save(commit=commit)
-
-
-class EpisodeForm(forms.ModelForm):
- class Meta:
- model = Episode
- exclude = ('slug',)
- widgets = {'emission': forms.HiddenInput(),
- 'tags': TagWidget()}
-
- def save(self, commit=True):
- if not self.instance.slug:
- self.instance.slug = slugify(self.instance.title)
- return super(EpisodeForm, self).save(commit=commit)
-
-
-class EpisodeNewForm(EpisodeForm):
- diffusion = forms.DateTimeField(label='First Diffusion',
- widget=DateTimeWidget)
-
- def save(self, commit=True):
- episode = super(EpisodeNewForm, self).save(commit=commit)
- diffusion = Diffusion()
- diffusion.episode_id = episode.id
- diffusion.datetime = self.cleaned_data.get('diffusion')
- diffusion.save()
- return episode
-
-
-class ScheduleForm(forms.ModelForm):
- class Meta:
- model = Schedule
- widgets = {
- 'emission': forms.HiddenInput(),
- 'datetime': DayAndHourWidget(),
- }
-
-
-class SoundFileForm(forms.ModelForm):
- class Meta:
- model = SoundFile
- widgets = {
- 'episode': forms.HiddenInput(),
- 'file': JqueryFileUploadInput(),
- }
-
-
-class DiffusionForm(forms.ModelForm):
- class Meta:
- model = Diffusion
- widgets = {
- 'episode': forms.HiddenInput(),
- 'datetime': DateTimeWidget(),
- }
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Code scavenged from Glasnost
-# By: Odile Bénassy <obenassy@entrouvert.com>
-# Romain Chantereau <rchantereau@entrouvert.com>
-# Nicolas Clapiès <nclapies@easter-eggs.org>
-# Pierre-Antoine Dejace <padejace@entrouvert.be>
-# Thierry Dulieu <tdulieu@easter-eggs.com>
-# Florent Monnier <monnier@codelutin.com>
-# Cédric Musso <cmusso@easter-eggs.org>
-# Frédéric Péters <fpeters@entrouvert.be>
-# Benjamin Poussin <poussin@codelutin.com>
-# Emmanuel Raviart <eraviart@entrouvert.com>
-# Sébastien Régnier <regnier@codelutin.com>
-# Emmanuel Saracco <esaracco@easter-eggs.com>
-#
-# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
-# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
-# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
-# Emmanuel Saracco & Théridion
-# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
-# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
-# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
-# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
-# Régnier, Emmanuel Saracco, Théridion & Vecam
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-import re
-import sys
-
-_non_id_chars = re.compile('[^a-z0-9]+')
-_non_id_at_ends = re.compile('^[-0-9]+|-+$')
-
-def enhanceTypo(s):
- # typographic junkie
- # idea from: http://daringfireball.net/projects/smartypants/
- s = s.replace('...', '…') # ellipsis (...)
- s = s.replace(' -- ', ' — ') # em-dash
- s = s.replace('(c)', '© ') # copyright symbol
- return s
-
-
-def parseSpipLink(link):
- link = link.replace('\n', ' ')
- matchObject = re.match(
- r'(?P<role>alias|art(icle)?|atom|book|card|election|file|'\
- 'grade|group|heading|im(g|age)?|person(ne)?|rubri(c|que)'\
- ') *(?P<localId>\S+) *(?P<option>\S+)?', link)
-
- if matchObject is None:
- name = link
- for prefix in [ 'http://', 'https://', 'ftp://', 'mailto:' ]:
- if name.startswith(prefix):
- if not '/' in name[len(prefix):]:
- name = name[len(prefix):]
- break
- else:
- name = ''
- return name, link
-
- role = matchObject.group('role')
- localId = matchObject.group('localId')
- option = matchObject.group('option') and \
- ':%s' % matchObject.group('option') or ''
-
- return ('XXX', '#')
-
-
-class Formatter:
- def close(self, **keywords):
- return ''
-
- def list(self, list):
- def getListIndent(stack):
- if len(stack) == 0:
- return -1
- else:
- return stack[-1][0]
- stack = []
- result = ''
- for line in list:
- indent, type, text = line
- while indent < getListIndent(stack):
- result += self.listEnd(len(stack), stack[-1][1])
- del stack[-1]
- if indent > getListIndent(stack):
- stack.append((indent, type))
- result += self.listBegin(len(stack) - 1, type)
- result += self.listItem(len(stack), text)
- while stack:
- result += self.listEnd(len(stack) - 1, stack[-1][1])
- del stack[-1]
- return result
-
- def open(self, **keywords):
- return ''
-
- def prescaleImage(self):
- return 1
-
- def table(self, table, hasHeader):
- result = ''
- rows = len(table)
- cols = max(map(len, table))
- result += self.tableBegin(rows, cols)
- for i in range(len(table)):
- row = table[i]
- rowNumber = i
- if hasHeader:
- rowNumber -= 1
- result += self.tableLineBegin(rowNumber,
- isHeader = i == 0 and hasHeader)
- j = 0
- for cell in row:
- if type(cell) in (str, unicode) and cell.strip() == '###':
- cell = rowNumber + 1
- result += self.tableCell(cell, rowNumber, j,
- isHeader = i == 0 and hasHeader)
- j += 1
- result += self.tableLineEnd(i, isHeader = i == 0 and hasHeader)
- result += self.tableEnd(isHeader = len(table) == 1 and hasHeader)
- return result
-
- def text(self, text):
- return text
-
-
-class FormatterHtml(Formatter):
- def __init__(self):
- self.states = [ '' ]
-
- def intertitle(self, text, sublevel = 0):
- nameText = re.sub('<.*?>', '', text).strip()
- # from docutils/nodes.py, def make_id(string)
- nameText = _non_id_chars.sub('-', ' '.join(nameText.lower().split()))
- nameText = _non_id_at_ends.sub('', nameText)
-
- return '<h%(sectionLevel)d id="%(nameText)s">%(text)s'\
- '</h%(sectionLevel)d>\n\n' % {
- 'text': text.strip(),
- 'sectionLevel': self.sectionLevel + sublevel,
- 'nameText': nameText,
- }
-
- def lineBreak(self):
- return '<br />\n'
-
- def list(self, list):
- # FIXME: the Formatter.list method doesn't work for sub-lists, so it is
- # rewritten here. Maybe this method should also be used by
- # Formatter.list
- def getListIndent(stack):
- if len(stack) == 0:
- return -1
- else:
- return stack[-1][0]
- self.states.append('blockLevel')
- stack = []
- result = ''
- for line in list:
- indent, type, text = line
- while indent < getListIndent(stack):
- result += self.listItemEnd()
- result += self.listEnd(len(stack), stack[-1][1])
- del stack[-1]
- if indent > getListIndent(stack):
- stack.append((indent, type))
- result += '\n'
- result += self.listBegin(len(stack) - 1, type)
- else:
- result += self.listItemEnd()
- result += self.listItemBegin(len(stack), text)
- while stack:
- result += self.listItemEnd()
- result += self.listEnd(len(stack) - 1, stack[-1][1])
- del stack[-1]
- return result
-
- def listBegin(self, indent, type):
- if type:
- type = 'ol'
- else:
- type = 'ul'
- return '%(indent)s<%(type)s>\n' % {
- 'indent': ' ' * indent,
- 'type': type,
- }
-
- def listEnd(self, indent, type):
- if type:
- type = 'ol'
- else:
- type = 'ul'
- return '%(indent)s</%(type)s>\n' % {
- 'indent': ' ' * indent,
- 'type': type,
- }
-
- def listItemBegin(self, indent, item):
- return '%(indent)s<li>%(item)s' % {
- 'indent': ' ' * indent,
- 'item': item.strip('*'),
- }
-
- def listItemEnd(self):
- return '</li>\n'
-
- def nonBreakingSpace(self):
- return ' '
-
- def open(self, **keywords):
- self.sectionLevel = 2
- if keywords.has_key('sectionLevel'):
- self.sectionLevel = int(keywords['sectionLevel'])
- return ''
-
- def paragraph(self, text):
-
- # turn URL into links
- def repl(match):
- m = match.group(0)
- if m[0] == '"' and m[-1] == '"':
- return m
- if m[0] in '>' and m[-1] == '<':
- return m
- m = m.rstrip('<').lstrip('>')
- return '<a href="%s">%s</a>' % (m, m)
- t1 = text
- text = re.sub(r'([">]?http[s]?://[a-zA-Z0-9\.\/-]*[<"]?)', repl, text, re.DOTALL)
-
- if self.states[-1] == 'blockLevel':
- self.states.pop()
- return text
-
-
- def line80(text):
- t = []
- i = 0
- while 1:
- val = text[i+70:].find(' ')
- if val == -1:
- t.append(text[i:])
- break
- part = text[i:i+70+val+1]
- t.append(part)
- i += len(part)
- return '\n'.join(t)
-
- text = enhanceTypo(text.strip())
- text = line80(text.replace('\n', ' '))
- text = text.replace('\n_ ', '\n<br/>\n')
- if not text:
- return self.lineBreak()
- return '<p>%(text)s</p>\n\n' % {
- 'text': text,
- }
-
- def preformatted(self, text):
- if not text:
- return ''
-## text = self.text(text)
- self.states.append('blockLevel')
- return '<pre>%(text)s</pre>' % {
- 'text': text,
- }
-
- def preformattedInline(self, text):
- if not text:
- return ''
- text = self.text(text)
- return '<code>%(text)s</code>' % {
- 'text': text,
- }
-
- def punctuationAndSpace(self, punctuation):
- return {
- u'« ': u'« ',
- }[punctuation]
-
- def spaceAndPunctuation(self, punctuation):
- return {
- u' :': u' :',
- u' ;': u' ;',
- u' !': u' !',
- u' ?': u' ?',
- u' »': u' »',
- u' %': u' %',
- u' ...': u' ...',
- }[punctuation]
-
- def tableBegin(self, rows, cols):
- self.states.append('blockLevel')
- return '<table>\n'
-
- def tableCell(self, cell, row, col, isHeader):
- if not cell:
- cell = ' '
- if isHeader:
- tag = 'th'
- attrtag = ' scope="col"'
- else:
- tag = 'td'
- attrtag = ''
- return ' <%(tag)s%(attrtag)s>%(cell)s</%(tag)s>\n' % {
- 'tag': tag,
- 'cell': cell.strip(),
- 'attrtag': attrtag,
- }
-
- def tableEnd(self, isHeader = 0):
- return '</table>\n'
-
- def tableLineBegin(self, tableLineCount, isHeader = 0):
- if isHeader:
- return ' <tr>\n'
- elif (tableLineCount + 1) % 2 == 0:
- return ' <tr class="even">\n'
- else:
- return ' <tr class="odd">\n'
-
- def tableLineEnd(self, tableLineCount, isHeader = 0):
- return ' </tr>\n'
-
- def text(self, text):
- if not text:
- return ''
- text = text.replace('&', '&')
- text = text.replace('<', '<')
- #text = text.replace('\x85', '…') # ellipsis (...)
- return text
-
-
-class FormatterHtmlComplete(FormatterHtml):
- _footNotes = None
-
- def close(self, **keywords):
- footNotes = self._footNotes
- if footNotes is None or len(footNotes) == 0:
- return ''
- indexes = footNotes.keys()
- indexes.sort()
- result = '<div class="spip-notes">\n'
- for index in indexes:
- result += '<p>'
- result += '[<a href="#nh%(index)s" name="nb%(index)s" '\
- 'class="spip-note">%(index)s</a>] %(text)s' % {
- 'index': index,
- 'text': footNotes[index],
- }
- result += '</p>\n'
- result += '</div>\n'
- return result
-
- def emphasis(self, text):
- if not text:
- return ''
- return '<em>%(text)s</em>' % {
- 'text': text,
- }
-
- def footNoteCall(self, footNote):
- if self._footNotes is None:
- self._footNotes = {}
- index = len(self._footNotes) + 1
- self._footNotes[index] = footNote
- return ' [<a href="#nb%(index)s" name="nh%(index)s" '\
- 'class="spip-note">%(index)s</a>]' % { 'index': index }
-
- def image(self, name, url, width=None, height=None, fullUrl=None, align=None):
- if width:
- width = ' width="%s"' % width
- else:
- width = ''
- if height:
- height = ' height="%s"' % height
- else:
- height = ''
- if align:
- align = ' style="float: %s;"' % align
- else:
- align = ''
- image = """\
-<img src="%(url)s" alt="%(name)s" title="%(name)s"%(height)s%(width)s%(align)s />\
-""" % {
- 'height': height,
- 'name': name,
- 'url': url,
- 'width': width,
- 'align': align,
- }
- if fullUrl:
- image = '<a href="%(fullUrl)s">%(image)s</a>' % {
- 'fullUrl': fullUrl,
- 'image': image,
- }
- return image
-
- def lineSeparator(self):
- return '<hr />\n'
-
- def link(self, name, url, title=None):
- url = url.replace('"', '"') # '"' must be converted.
- # The following replace should not be done. An url must be left as is.
- # url = url.replace('&', '&') #
- # url = url.replace('<', '<') # ?
- # url = url.replace('>', '>') # ?
- attrs = ['href="%s"' % url]
- if title:
- attrs.append('title="%s"' % title)
- if url.startswith('http://'):
- attrs.append('class="external"')
- attrs = ' '.join(attrs)
- return '<a %s>%s</a>' % (attrs, name)
-
- def strong(self, text):
- if not text:
- return ''
- return '<strong>%(text)s</strong>' % {
- 'text': text,
- }
-
- def teletype(self, text):
- if not text:
- return ''
- return '<tt>%(text)s</tt>' % {
- 'text': text,
- }
-
-
-class FormatterHtmlSimple(FormatterHtml):
- def emphasis(self, text):
- return text
-
- def footNoteCall(self, footNote):
- return ''
-
- def image(self, name, url, width = None, height = None, fullUrl = None):
- return ''
-
- def lineSeparator(self):
- return '<br />\n'
-
- def link(self, name, url, title=None):
- return str(name)
-
- def strong(self, text):
- return text
-
- def teletype(self, text):
- return text
-
-
-
-class SpipParser:
- codeRegexp = r"""
-(?P<codeStop>\</(code|CODE)\>)
-|(?P<wordAsIs>\w+)
-"""
- codeRegexp = codeRegexp.replace('\n', '')
- codeRegexpObject = None
- footNoteRegexp = r"""
-(?P<footNoteStop>\]\])
-|(?P<image>\<((im(g|age)?)|(IM(G|AGE)?)) *(\d+|[^ \>]+)( +\d+\*\d+)?\>)
-|(?P<teletypeStart>\(\()
-|(?P<teletypeStop>\)\))
-|(?P<strongStart>\{\{)
-|(?P<strongStop>\}\})
-|(?P<emphasisStart>\{)
-|(?P<emphasisStop>\})
-|(?P<linkStart>\[)
-|(?P<antislash>\\.?)
-|(?P<punctuationAndSpace>[«] )
-|(?P<spaceAndPunctuation> ([:;!\?»%]|\.\.\.))
-|(?P<nonBreakingSpace>~)
-|(?P<word>\w+)
-"""
- footNoteRegexp = footNoteRegexp.replace('\n', '')
- footNoteRegexpObject = None
- linkNameRegexp = r"""
-(?P<image>\<((im(g|age)?)|(IM(G|AGE)?)) *(\d+|[^ \>]+)( +\d+\*\d+)?\>)
-|(?P<teletypeStart>\(\()
-|(?P<teletypeStop>\)\))
-|(?P<strongStart>\{\{)
-|(?P<strongStop>\}\})
-|(?P<emphasisStart>\{)
-|(?P<emphasisStop>\})
-|(?P<linkMiddle>->)
-|(?P<linkWithoutMiddleStop>\])
-|(?P<antislash>\\.?)
-|(?P<punctuationAndSpace>[«] )
-|(?P<spaceAndPunctuation> ([:;!\?»%]|\.\.\.))
-|(?P<nonBreakingSpace>~)
-|(?P<word>\w+)
-"""
- linkNameRegexp = linkNameRegexp.replace('\n', '')
- linkNameRegexpObject = None
- linkRegexp = r"""
-(?P<linkStop>\])
-|(?P<wordInUrl>\w+)
-"""
- linkRegexp = linkRegexp.replace('\n', '')
- linkRegexpObject = None
- listRegexp = r"""
-(?P<listLineStart>^ *-([0-9aAiI]\.)?(?=[^-]))
-|(?P<listLineStop>\r?\n(?= *-([0-9aAiI]\.)?(?=[^-])))
-|(?P<listLineContinuation>\r?\n(?= +))
-|(?P<listStop>(?=\r?\n|$))
-|(?P<image>\<((im(g|age)?)|(IM(G|AGE)?)) *(\d+|[^ \>]+)( +\d+\*\d+)?\>)
-|(?P<teletypeStart>\(\()
-|(?P<teletypeStop>\)\))
-|(?P<strongStart>\{\{)
-|(?P<strongStop>\}\})
-|(?P<emphasisStart>\{)
-|(?P<emphasisStop>\})
-|(?P<footNoteStart>\[\[)
-|(?P<linkStart>\[)
-|(?P<antislash>\\.?)
-|(?P<punctuationAndSpace>[«] )
-|(?P<spaceAndPunctuation> ([:;!\?»%]|\.\.\.))
-|(?P<nonBreakingSpace>~)
-|(?P<word>\w+)
-"""
- listRegexp = listRegexp.replace('\n', '')
- listRegexpObject = None
- paragraphRegexp = r"""
-(?P<paragraphStop>\r?\n( *\r?\n)* *(?=\r?\n|$))
-|(?P<lineSeparator>^ *[-_]{4,} *(\r?\n|$))
-|(?P<intertitleStart>^ *\{\{\{)
-|(?P<intertitleStop>\}\}\}( *$|))
-|(?P<listStart>^ *-([0-9aAiI]\.)?)
-|(?P<tableWithHeaderStart>^ *\|(?=( *\{\{.*?\}\} *\|)+ *(\r?\n|$)))
-|(?P<tableStart>^ *\|)
-|(?P<codeStart>\<(code|CODE)\>)
-|(?P<image>\<((im(g|age)?)|(IM(G|AGE)?)) *(\d+|[^ \>]+)( +\d+\*\d+)?\>)
-|(?P<teletypeStart>\(\()
-|(?P<teletypeStop>\)\))
-|(?P<strongStart>\{\{)
-|(?P<strongStop>\}\})
-|(?P<emphasisStart>\{)
-|(?P<emphasisStop>\})
-|(?P<footNoteStart>\[\[)
-|(?P<linkStart>\[)
-|(?P<antislash>\\.?)
-|(?P<punctuationAndSpace>[«] )
-|(?P<spaceAndPunctuation> ([:;!\?»%]|\.\.\.))
-|(?P<nonBreakingSpace>~)
-|(?P<word>\w+)
-"""
- paragraphRegexp = paragraphRegexp.replace('\n', '')
- paragraphRegexpObject = None
- posDelta = 0
- spipRegexp = r"""
-(?P<paragraphStart>\r?\n)
-"""
- spipRegexp = spipRegexp.replace('\n', '')
- spipRegexpObject = None
- states = None
- tableRegexp = r"""
-(?P<rowStart>^ *\|)
-|(?P<rowStop>\| *\r?\n(?= *\|))
-|(?P<tableStop>\| *(?=\r?\n|$))
-|(?P<cellRestart>\|)
-|(?P<image>\<((im(g|age)?)|(IM(G|AGE)?)) *(\d+|[^ \>]+)( +\d+\*\d+)?\>)
-|(?P<teletypeStart>\(\()
-|(?P<teletypeStop>\)\))
-|(?P<strongStart>\{\{)
-|(?P<strongStop>\}\})
-|(?P<emphasisStart>\{)
-|(?P<emphasisStop>\})
-|(?P<footNoteStart>\[\[)
-|(?P<linkStart>\[)
-|(?P<antislash>\\.?)
-|(?P<punctuationAndSpace>[«] )
-|(?P<spaceAndPunctuation> ([:;!\?»%]|\.\.\.))
-|(?P<nonBreakingSpace>~)
-|(?P<word>\w+)
-"""
- tableRegexp = tableRegexp.replace('\n', '')
- tableRegexpObject = None
-
- def __init__(self, documents):
- self.documents = documents
-
- self.codeRegexpObject = re.compile(self.codeRegexp,
- re.MULTILINE | re.DOTALL)
- self.footNoteRegexpObject = re.compile(self.footNoteRegexp,
- re.MULTILINE | re.DOTALL)
- self.linkNameRegexpObject = re.compile(self.linkNameRegexp,
- re.MULTILINE | re.DOTALL)
- self.linkRegexpObject = re.compile(self.linkRegexp,
- re.MULTILINE | re.DOTALL)
- self.listRegexpObject = re.compile(self.listRegexp,
- re.MULTILINE | re.DOTALL)
- self.paragraphRegexpObject = re.compile(self.paragraphRegexp,
- re.MULTILINE | re.DOTALL)
- self.spipRegexpObject = re.compile(self.spipRegexp,
- re.MULTILINE | re.DOTALL)
- self.tableRegexpObject = re.compile(self.tableRegexp,
- re.MULTILINE | re.DOTALL)
- self.states = []
- self.pushState({
- 'state': None,
- })
- self.pushState({
- 'formattedText': '',
- 'paragraphsCount': 0,
- 'regexpObject': self.spipRegexpObject,
- 'state': 'spip',
- })
- self.pushState({
- 'formattedText': '',
- 'ignoreEmptyParagraph': 0,
- 'regexpObject': self.paragraphRegexpObject,
- 'state': 'paragraph',
- })
-
- def format(self, formatter, rawText, **keywords):
- self.formatter = formatter
- formattedText = self.formatter.open(**keywords)
- if not rawText:
- rawText = ''
- rawText = rawText.expandtabs()
- pos = 0
- while pos < len(rawText):
- regexpObject = self.getVar('regexpObject')
- matchObject = regexpObject.match(rawText, pos)
- if matchObject is None or matchObject.lastgroup is None:
- self.setVar(
- 'formattedText',
- self.getVar('formattedText') \
- + self.formatter.text(rawText[pos]))
- pos += 1
- else:
- groupName = matchObject.lastgroup
- result = apply(getattr(self, 'handle_' + groupName),
- (matchObject.group(groupName), ))
- if result:
- self.setVar('formattedText',
- self.getVar('formattedText') + result)
- pos = matchObject.end(groupName) + self.posDelta
- if self.posDelta != 0:
- del self.posDelta
- while len(self.states) > 2:
- if self.getVar('state') == 'list':
- result = self.handle_listStop(None)
- if result:
- self.setVar('formattedText',
- self.getVar('formattedText') + result)
- elif self.getVar('state') == 'paragraph':
- result = self.handle_paragraphStop(None, isLastParagraph = 1)
- if result:
- self.setVar('formattedText',
- self.getVar('formattedText') + result)
- else:
- self.pullState()
- formattedText += self.getVar('formattedText')
- formattedText = formattedText.strip() + '\n'
- formattedText += self.formatter.close(**keywords)
- return formattedText
-
- def getVar(self, name):
- for state in self.states:
- if state.has_key(name):
- return state[name]
- else:
- raise KeyError(name)
-
- def getPreviousVar(self, name):
- for state in self.states[1:]:
- if state.has_key(name):
- return state[name]
- else:
- raise KeyError(name)
-
- def handle_antislash(self, group):
- character = group[1]
- if character == 'n':
- return self.formatter.lineBreak()
- else:
- return self.formatter.text(character)
-
- def handle_cellRestart(self, group):
- self.handle_cellStop(group)
- self.handle_cellStart(group)
- return None
-
- def handle_cellStart(self, group):
- table = self.getVar('table')
- table[-1].append([])
- return None
-
- def handle_cellStop(self, group):
- table = self.getVar('table')
- table[-1][-1] = self.getVar('formattedText')
- self.setVar('formattedText', '')
- return None
-
- def handle_codeStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'regexpObject': self.codeRegexpObject,
- 'state': 'code',
- })
- return None
-
- def handle_codeStop(self, group):
- if self.getVar('state') != 'code':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.preformatted(formattedText)
-
- def handle_emphasisStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'state': 'emphasis',
- })
- return None
-
- def handle_emphasisStop(self, group):
- if self.getVar('state') != 'emphasis':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.emphasis(formattedText)
-
- def handle_footNoteStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'regexpObject': self.footNoteRegexpObject,
- 'state': 'footNote',
- })
- return None
-
- def handle_footNoteStop(self, group):
- if self.getVar('state') != 'footNote':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.footNoteCall(formattedText)
-
- def handle_image(self, group):
- matchObject = re.match(
- r'\<((im(g|age)?)|(IM(G|AGE)?)) '\
- '*((?P<localId>\d+)|(?P<url>[^ \>]+))'\
- '(?P<align>\|[a-z]+)?'\
- '( +(?P<width>\d+)\*(?P<height>\d+))?\>', group)
- localId = matchObject.group('localId')
- url = matchObject.group('url')
- width = matchObject.group('width')
- height = matchObject.group('height')
- align = matchObject.group('align')
- name = localId
- if align:
- align = align[1:]
- if not url and localId:
- doc = self.documents.get(localId)
- if doc and doc.filename:
- url = '/media/IMG/' + doc.filename
- fullUrl = None
- return self.formatter.image(name, url, width, height, fullUrl, align)
-
- def handle_intertitleStart(self, group):
- inParagraph = self.getVar('state') == 'paragraph'
- if inParagraph:
- result = self.handle_paragraphStop(None, ignoreEmptyParagraph = 1)
- if result:
- self.setVar('formattedText',
- self.getVar('formattedText') + result)
- self.pushState({
- 'formattedText': '',
- 'inParagraph': inParagraph,
- 'regexpObject': self.paragraphRegexpObject,
- 'state': 'intertitle',
- })
- return None
-
- def handle_intertitleStop(self, group):
- if self.getVar('state') == 'intertitle':
- formattedText = self.getVar('formattedText')
- inParagraph = self.getVar('inParagraph')
- self.pullState()
- formattedText = self.formatter.intertitle(formattedText)
- self.setVar('formattedText',
- self.getVar('formattedText') + formattedText)
- if inParagraph:
- return self.handle_paragraphStart(None,
- ignoreEmptyParagraph = 1)
- else:
- return None
- elif self.getVar('state') == 'strong':
- self.posDelta -= 1
- return self.handle_strongStop(group[:-1])
- elif self.getVar('state') == 'emphasis':
- self.posDelta -= 2
- return self.handle_emphasisStop(group[:-2])
- else:
- return None
-
- def handle_lineSeparator(self, group):
- inParagraph = self.getVar('state') == 'paragraph'
- if inParagraph:
- result = self.handle_paragraphStop(None, ignoreEmptyParagraph = 1)
- if result:
- self.setVar('formattedText',
- self.getVar('formattedText') + result)
- formattedText = self.formatter.lineSeparator()
- self.setVar('formattedText',
- self.getVar('formattedText') + formattedText)
- if inParagraph:
- return self.handle_paragraphStart(None, ignoreEmptyParagraph = 1)
- else:
- return None
-
- def handle_linkMiddle(self, group):
- if self.getVar('state') != 'linkName':
- return None
- name = self.getVar('formattedText')
- self.pullState()
- self.pushState({
- 'formattedText': '',
- 'name': name,
- 'regexpObject': self.linkRegexpObject,
- 'state': 'link',
- })
- return None
-
- def handle_linkStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'regexpObject': self.linkNameRegexpObject,
- 'state': 'linkName',
- })
- return None
-
- def handle_linkStop(self, group):
- if self.getVar('state') != 'link':
- return None
- title = None
- name = self.getVar('name')
- link = self.getVar('formattedText')
- self.pullState()
- link = link.strip()
- title, url = parseSpipLink(link)
- if not title:
- title = url
- if name and '|' in name:
- oTitle = title
- try:
- name, title = name.split('|', 2)
- except ValueError:
- # XXX
- print 'error splitting', repr(name)
- name, title = oTitle, 'XXX'
- if not name:
- name = oTitle
- elif not name:
- name = title
- title = None
- if name == title or url == title:
- title = None
- return self.formatter.link(name.strip(), url, title)
-
- def handle_linkWithoutMiddleStop(self, group):
- if self.getVar('state') != 'linkName':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.text('[') \
- + formattedText \
- + self.formatter.text(']')
-
- def handle_listLineStart(self, group):
- matchObject = re.match(
- r'^(?P<indent> *)-((?P<type>[0-9aAiI])\.)?',
- group)
- indent = len(matchObject.group('indent'))
- type = matchObject.group('type')
- list = self.getVar('list')
- list.append([indent, type, None])
- return None
-
- def handle_listLineContinuation(self, group):
- return None
-
- def handle_listLineStop(self, group):
- list = self.getVar('list')
- list[-1][-1] = self.getVar('formattedText').lstrip()
- self.setVar('formattedText', '')
- return None
-
- def handle_listStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'list': [],
- 'regexpObject': self.listRegexpObject,
- 'state': 'list',
- })
- return self.handle_listLineStart(group)
-
- def handle_listStop(self, group):
- if self.getVar('state') != 'list':
- # The following pullState is mandatory, because group is empty, so
- # if we don't pull a state, handle_listStop will be called forever.
- if len(self.states) > 2:
- self.pullState()
- return None
- self.handle_listLineStop(group)
- list = self.getVar('list')
- self.pullState()
- return self.formatter.list(list)
-
- def handle_nonBreakingSpace(self, group):
- return self.formatter.nonBreakingSpace()
-
- def handle_paragraphStart(self, group, ignoreEmptyParagraph = 1):
- self.pushState({
- 'formattedText': '',
- 'ignoreEmptyParagraph': ignoreEmptyParagraph,
- 'regexpObject': self.paragraphRegexpObject,
- 'state': 'paragraph',
- })
- return None
-
- def handle_paragraphStop(self, group, ignoreEmptyParagraph = 0,
- isLastParagraph = 0):
- if self.getVar('state') != 'paragraph':
- return None
- formattedText = self.getVar('formattedText').strip()
- ignoreEmptyParagraph = ignoreEmptyParagraph \
- or self.getVar('ignoreEmptyParagraph')
- self.pullState()
- self.setVar('paragraphsCount', self.getVar('paragraphsCount') + 1)
- if ignoreEmptyParagraph and not formattedText:
- return None
- elif isLastParagraph and self.getVar('paragraphsCount') == 1:
- return formattedText
- elif re.match('^<strong>.+</strong>$', formattedText) and \
- len(re.findall('<strong>.+?</strong>', formattedText)) == 1:
- formattedText = formattedText[8:-9]
- return self.formatter.intertitle(formattedText, sublevel = 1)
- else:
- return self.formatter.paragraph(formattedText)
-
- def handle_punctuationAndSpace(self, punctuation):
- return self.formatter.punctuationAndSpace(punctuation)
-
- def handle_rowStart(self, group):
- table = self.getVar('table')
- table.append([])
- return self.handle_cellStart(group)
-
- def handle_rowStop(self, group):
- return self.handle_cellStop(group)
-
- def handle_spaceAndPunctuation(self, punctuation):
- return self.formatter.spaceAndPunctuation(punctuation)
-
- def handle_strongStart(self, group):
- if self.getVar('state') == 'table' and self.getVar('hasHeader'):
- return None
- self.pushState({
- 'formattedText': '',
- 'state': 'strong',
- })
- return None
-
- def handle_strongStop(self, group):
- if self.getVar('state') != 'strong':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.strong(formattedText)
-
- def handle_tableStart(self, group, hasHeader = 0):
- self.pushState({
- 'formattedText': '',
- 'hasHeader': hasHeader,
- 'table': [],
- 'regexpObject': self.tableRegexpObject,
- 'state': 'table',
- })
- return self.handle_rowStart(group)
-
- def handle_tableStop(self, group):
- self.handle_rowStop(group)
- table = self.getVar('table')
- hasHeader = self.getVar('hasHeader')
- self.pullState()
- return self.formatter.table(table, hasHeader)
-
- def handle_tableWithHeaderStart(self, group):
- return self.handle_tableStart(group, hasHeader = 1)
-
- def handle_teletypeStart(self, group):
- self.pushState({
- 'formattedText': '',
- 'state': 'teletype',
- })
- return None
-
- def handle_teletypeStop(self, group):
- if self.getVar('state') != 'teletype':
- return None
- formattedText = self.getVar('formattedText')
- self.pullState()
- return self.formatter.teletype(formattedText)
-
- def handle_word(self, word):
- return self.formatter.text(word)
-
- def handle_wordAsIs(self, word):
- return word
-
- def handle_wordInUrl(self, word):
- return word
-
- def hasVar(self, name):
- for state in self.states:
- if state.has_key(name):
- return 1
- else:
- return 0
-
- def pullState(self):
- del self.states[0]
-
- def pushState(self, state):
- self.states.insert(0, state)
-
- def setVar(self, name, value):
- self.states[0][name] = value
-
-
-def makeHtmlFromSpip(text, simple=0, inline=0, documents=None, **keywords):
- if not text:
- return ''
-
- text = text.replace('\r\n', '\n').replace('<quote></quote>', '')
- #text = text.replace('\x91', "'").replace('\x92', "'").replace(
- # '\x93', "'").replace('\x94', "'").replace(
- # '\x81', "'").replace('\x82', "'").replace(
- # '’', "'").replace('…', '...').replace(
- # '–', '--').replace('“', '"').replace(
- # '´', "'").replace('”', '"').replace(
- # '‘', "'").replace('œ', 'oe')
-
- if not inline:
- # Force the spip parser to produce paragraphs.
- text += '\n\n'
- parser = SpipParser(documents=documents)
- if simple:
- formatter = FormatterHtmlSimple()
- else:
- formatter = FormatterHtmlComplete()
- return parser.format(formatter, text, **keywords).strip()
-
-
-if __name__ == '__main__':
- print makeHtmlFromSpip(unicode(file(sys.argv[1]).read(), 'utf-8'))
+++ /dev/null
-import base64
-import mutagen
-import mutagen.mp3
-import os
-import subprocess
-
-from optparse import make_option
-
-from django.core.management.base import BaseCommand, CommandError
-
-from ...models import SoundFile
-
-
-class Command(BaseCommand):
-
- option_list = BaseCommand.option_list + (
- make_option('--force',
- action='store_true',
- dest='force',
- default=False,
- help='Create files even if they exist'),
- make_option('--reset-metadata',
- action='store_true',
- dest='reset_metadata',
- default=False,
- help='Reset metadata on all files'),
- make_option('--emission',
- dest='emission',
- metavar='EMISSION',
- default=None,
- help='Process files belonging to emission only'),
- make_option('--episode',
- dest='episode',
- metavar='EPISODE',
- default=None,
- help='Process files belonging to episode only'),
- )
-
- def handle(self, force, reset_metadata, emission, episode, verbosity, **kwargs):
- self.verbose = (verbosity > 1)
-
- for soundfile in SoundFile.objects.select_related().exclude(podcastable=False):
- if emission and soundfile.episode.emission.slug != emission:
- continue
- if episode and soundfile.episode.slug != episode:
- continue
- if soundfile.file is None or not os.path.exists(soundfile.file.path):
- continue
- for format in ('ogg', 'mp3'):
- file_path = soundfile.get_format_path(format)
- if not os.path.exists(file_path) or force:
- self.create(soundfile, format)
- if force or reset_metadata:
- self.set_metadata(soundfile, format)
-
- def create(self, soundfile, format):
- file_path = soundfile.get_format_path(format)
-
- cmd = ['sox', soundfile.file.path, file_path]
-
- if format == 'ogg':
- cmd[-1:-1] = ['-C', '4'] # q4 (~128kbps)
- elif format == 'mp3':
- cmd[-1:-1] = ['-C', '-4'] # vbr @ ~128kbps
-
- if self.verbose:
- print 'creating', file_path
- cmd[1:1] = ['--show-progress']
- print ' ', ' '.join(cmd)
-
- subprocess.call(cmd)
-
- def set_metadata(self, soundfile, format):
- file_path = soundfile.get_format_path(format)
-
- if format == 'mp3':
- audio = mutagen.mp3.MP3(file_path, ID3=mutagen.easyid3.EasyID3)
- elif format == 'ogg':
- audio = mutagen.File(file_path)
-
- if 'comment' in audio:
- del audio['comment']
- if soundfile.fragment is True and soundfile.title:
- audio['title'] = '%s - %s' % (
- soundfile.episode.title,
- soundfile.title)
- else:
- audio['title'] = soundfile.episode.title
- audio['album'] = soundfile.episode.emission.title
- audio['artist'] = 'Radio Panik'
-
- if soundfile.episode.image or soundfile.episode.emission.image:
- image = (soundfile.episode.image or soundfile.episode.emission.image)
- image.file.open()
- if os.path.splitext(image.path)[1].lower() in ('.jpeg', '.jpg'):
- mimetype = 'image/jpeg'
- elif os.path.splitext(image.path)[1].lower() == '.png':
- mimetype = 'image/png'
- else:
- mimetype = None
- if mimetype:
- if format == 'ogg':
- audio['coverartmime'] = mimetype
- audio['coverartdescription'] = 'image'
- audio['coverart'] = base64.encodestring(image.read()).replace('\n', '')
- elif format == 'mp3':
- audio.save()
- audio = mutagen.mp3.MP3(file_path)
- audio.tags.add(mutagen.id3.APIC(
- encoding=3, description='image',
- type=3, mime=mimetype, data=image.read()))
- image.close()
-
- audio.save()
+++ /dev/null
-from datetime import datetime
-
-from django.core.management.base import BaseCommand, CommandError
-
-from ...utils import day_program
-
-
-class Command(BaseCommand):
- def handle(self, year, month, day, **options):
- date = datetime(int(year), int(month), int(day))
- for entry in day_program(date):
- print entry.datetime, entry
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-from datetime import datetime
-import time
-import gzip
-import xml.etree.ElementTree as ET
-import os
-import re
-import urllib2
-
-from optparse import make_option
-
-from django.conf import settings
-from django.core.files import File
-from django.core.management.base import BaseCommand, CommandError
-from django.core.urlresolvers import reverse
-from django.utils.text import slugify
-
-from ...models import Emission, Episode, Diffusion, Category, SoundFile, NewsItem
-from ...models import get_sound_path
-
-
-from _spip2html import makeHtmlFromSpip
-
-
-class Rubric(object):
- archived = False
-
- spip_url_marker = '-'
- spip_url_object_name = 'rubrique'
-
- def __init__(self):
- self.articles = {}
- self.rubrics = {}
- self.categories = []
-
- @property
- def id(self):
- return self.id_rubrique
-
-
-class Article(object):
- spip_url_marker = ''
- spip_url_object_name = 'article'
-
- @property
- def id(self):
- return self.id_article
-
-
-class Breve(object):
- spip_url_marker = '+'
- spip_url_object_name = 'breve'
-
- @property
- def id(self):
- return self.id_breve
-
-
-class KeywordGroup(object):
- def __init__(self):
- self.keywords = {}
-
-
-class Keyword(object):
- related_object = None
-
-
-class Document(object):
- pass
-
-
-class Command(BaseCommand):
- args = 'filename'
- help = 'Load emissions and episodes from a Spip dump file'
-
- option_list = BaseCommand.option_list + (
- make_option('--no-updates',
- action='store_true',
- dest='dont_update',
- default=False,
- help='Only create new objects, do not update existing ones'),
- make_option('--stats-skipped',
- dest='stats_skipped_file',
- metavar='FILE',
- default=None,
- help='Create a CSV file ith skipped articles'),
- make_option('--rewritemap',
- dest='rewritemap_file',
- metavar='FILE',
- default=None,
- help='Create a Apache RewriteMap'),
- )
-
- def handle(self, filename, dont_update, rewritemap_file, stats_skipped_file, **options):
- self.do_updates = (not dont_update)
- if rewritemap_file:
- self.rewritemap = []
- if stats_skipped_file:
- self.stats_skipped_file = file(stats_skipped_file, 'w')
- else:
- self.stats_skipped_file = None
- with open(filename) as fd:
- content = fd.read()
- # the spip_courriers parts of the spip export are not properly
- # encoded, we manually remove them here so the XML file can be
- # parsed correctly.
- content = content[:content.find('<spip_courriers>')] + \
- content[content.rfind('</spip_courriers>')+17:]
- self.root = ET.fromstring(content)
-
- self.load_keyword_groups()
- self.load_keywords()
- self.load_rubrics()
-
- emission_rubric_ids = []
- straight_emission_rubric_ids = []
- for rubric in self.rubrics['2'].rubrics.values(): # 'Les emissions'
- emission_rubric_ids.append(rubric.id_rubrique)
- straight_emission_rubric_ids.append(rubric.id_rubrique)
- for subrubric in rubric.rubrics.values():
- emission_rubric_ids.append(subrubric.id_rubrique)
-
- self.load_breves()
- self.load_articles(emission_rubric_ids)
-
- self.set_urls()
-
- self.load_documents()
- self.load_document_links()
-
- if self.do_updates:
- self.process_emission_keywords()
- self.process_episode_keywords()
-
- for emission_id in straight_emission_rubric_ids:
- rubric = self.rubrics[emission_id]
- emission = self.get_or_create_emission(rubric)
- if rewritemap_file:
- self.add_rewritemap_entries(rubric, emission)
-
- for article in rubric.articles.values():
- episode = self.get_or_create_episode(article, emission)
- if episode is None:
- continue
- if rewritemap_file:
- self.add_rewritemap_entries(article, episode)
-
- self.set_sound_files(article, episode)
-
- for breve in self.breves.values():
- newsitem = self.get_or_create_newsitem(breve)
- if rewritemap_file:
- self.add_rewritemap_entries(breve, newsitem)
-
- if rewritemap_file:
- self.write_rewritemap(rewritemap_file)
-
- if self.stats_skipped_file:
- self.stats_skipped_file.close()
-
- def load_keyword_groups(self):
- self.keyword_groups = {}
- for keywordgroup_xml in self.root.iter('spip_groupes_mots'):
- keyword_group = KeywordGroup()
- for attr in ('id_groupe', 'titre'):
- setattr(keyword_group, attr, keywordgroup_xml.find(attr).text)
- if keyword_group.id_groupe not in ('11', # archives
- '12', # subjects
- '3', # category
- '10', # transversal
- ):
- continue
- self.keyword_groups[keyword_group.id_groupe] = keyword_group
-
- def load_keywords(self):
- self.keywords = {}
- for keyword_xml in self.root.iter('spip_mots'):
- keyword = Keyword()
- for attr in ('id_mot', 'titre', 'id_groupe'):
- setattr(keyword, attr, keyword_xml.find(attr).text)
- if not keyword.id_groupe in self.keyword_groups:
- continue
- if keyword.id_mot in ('92',): # blacklist
- continue
- self.keywords[keyword.id_mot] = keyword
- self.keyword_groups[keyword.id_groupe] = keyword
-
- def load_rubrics(self):
- self.rubrics = {}
- for rubric_xml in self.root.iter('spip_rubriques'):
- rubric = Rubric()
- for attr in ('id_rubrique', 'id_parent', 'titre',
- 'descriptif', 'texte'):
- setattr(rubric, attr, rubric_xml.find(attr).text)
- self.rubrics[rubric.id_rubrique] = rubric
-
- for rubric in self.rubrics.values():
- if rubric.id_parent and rubric.id_parent != '0':
- self.rubrics[rubric.id_parent].rubrics[rubric.id_rubrique] = rubric
-
- def load_breves(self):
- self.breves = {}
- for breve_xml in self.root.iter('spip_breves'):
- breve = Breve()
- for attr in ('id_breve', 'titre', 'texte',
- 'date_heure', 'statut'):
- setattr(breve, attr, breve_xml.find(attr).text)
- if breve.statut != 'publie':
- continue
- self.breves[breve.id_breve] = breve
-
- def load_articles(self, emission_rubric_ids):
- self.articles = {}
- for article_xml in self.root.iter('spip_articles'):
- if article_xml.find('id_rubrique').text == '65':
- pass # rubric for events, handle with care
- elif not article_xml.find('id_rubrique').text in emission_rubric_ids:
- continue
- article = Article()
- for attr in ('id_rubrique', 'id_article', 'titre', 'surtitre',
- 'soustitre', 'descriptif', 'chapo', 'texte',
- 'date_redac', 'statut', 'date'):
- setattr(article, attr, article_xml.find(attr).text)
-
- if article.id_rubrique == '65':
- # this is an event, they get a special handling, to be
- # merged with newsitems
- if article.statut not in ('publie', 'prop'):
- continue
- breve = Breve()
- breve.id_breve = '0%s' % article.id_article
- breve.titre = article.titre
- breve.texte = article.texte
- breve.date_heure = article.date
- self.breves[breve.id_breve] = breve
- continue
-
- if article.statut != 'publie':
- continue
- article.mots_cles = []
- self.articles[article.id_article] = article
-
- if self.rubrics[article.id_rubrique].id_parent != '2':
- # the spip structure didn't really expect subrubrics in the
- # 'emissions' section, but people added some nevertheless,
- # move related articles to their parent rubric.
- article.id_rubrique = self.rubrics[article.id_rubrique].id_parent
-
- self.rubrics[article.id_rubrique].articles[article.id_article] = article
-
- def set_urls(self):
- for spip_url_xml in self.root.iter('spip_urls'):
- id_objet = spip_url_xml.find('id_objet').text
- url = spip_url_xml.find('url').text
- if spip_url_xml.find('type').text == 'article' and id_objet in self.articles:
- self.articles[id_objet].url = url
- elif spip_url_xml.find('type').text == 'article' and ('0%s' % id_objet) in self.breves:
- self.breves['0' + id_objet].url = url
- elif spip_url_xml.find('type').text == 'rubrique' and id_objet in self.rubrics:
- self.rubrics[id_objet].url = url
- elif spip_url_xml.find('type').text == 'mot' and id_objet in self.keywords:
- self.keywords[id_objet].url = url
- elif spip_url_xml.find('type').text == 'breve' and id_objet in self.breves:
- self.breves[id_objet].url = url
-
- def load_documents(self):
- self.documents = {}
- for spip_doc_xml in self.root.iter('spip_documents'):
- id_document = spip_doc_xml.find('id_document').text
- doc = Document()
- doc.filename = spip_doc_xml.find('fichier').text
- doc.title = spip_doc_xml.find('titre').text
- if spip_doc_xml.find('distant').text == 'oui':
- url = doc.filename
- doc.filename = os.path.split(url)[-1]
- filename = os.path.join('media/IMG/', doc.filename)
- if not os.path.exists('media/IMG'):
- continue
- if not os.path.exists(filename):
- fd = file(filename, 'w')
- fd.write(urllib2.urlopen(url).read())
- fd.close()
- self.documents[id_document] = doc
-
- def load_document_links(self):
- self.attached_documents = {}
- for spip_doc_liens_xml in self.root.iter('spip_documents_liens'):
- id_document = spip_doc_liens_xml.find('id_document').text
- id_object = spip_doc_liens_xml.find('id_objet').text
- if spip_doc_liens_xml.find('objet').text != 'article':
- continue
- if not self.attached_documents.get(id_object):
- self.attached_documents[id_object] = []
- self.attached_documents[id_object].append(self.documents.get(id_document))
-
- def process_emission_keywords(self):
- for rubrickeyword_xml in self.root.iter('spip_mots_rubriques'):
- keyword_id = rubrickeyword_xml.find('id_mot').text
- rubric_id = rubrickeyword_xml.find('id_rubrique').text
- rubric = self.rubrics.get(rubric_id)
- if not rubric:
- continue
-
- if keyword_id == '100': # archive
- rubric.archived = True
- continue
-
- keyword = self.keywords.get(keyword_id)
- if keyword is None:
- continue
-
- if keyword.id_groupe == '3': # category
- rubric.categories.append(keyword)
- if not keyword.related_object:
- cs = Category.objects.filter(title=keyword.titre)
- if len(cs):
- c = cs[0]
- else:
- c = Category()
- c.title = keyword.titre
- c.save()
- keyword.related_object = c
-
- def process_episode_keywords(self):
- for articlekeyword_xml in self.root.iter('spip_mots_articles'):
- keyword_id = articlekeyword_xml.find('id_mot').text
- article_id = articlekeyword_xml.find('id_article').text
- article = self.articles.get(article_id)
- if not article:
- continue
-
- keyword = self.keywords.get(keyword_id)
- if keyword is None:
- continue
-
- if keyword.id_groupe in ('10', '12'): # transversales & sujets
- article.mots_cles.append(keyword.titre)
-
- def get_or_create_emission(self, rubric):
- slug = rubric.url.lower()
- possible_slugs = [rubric.url.lower(), rubric.url.lower().split(',')[0]]
- for slug in possible_slugs:
- try:
- emission = Emission.objects.get(slug=slug)
- break
- except Emission.DoesNotExist:
- continue
- else:
- emission = Emission()
-
- emission.slug = possible_slugs[-1]
-
- if emission.id and not self.do_updates:
- return emission
-
- slug = slug.split(',')[0]
- emission.slug = slug
- emission.title = rubric.titre
- emission.archived = rubric.archived
- emission.description = makeHtmlFromSpip(rubric.descriptif,
- documents=self.documents) or None
- emission.text = makeHtmlFromSpip(rubric.texte,
- documents=self.documents) or None
-
- image_path = None
- for ext in ('.jpg', '.png', '.gif'):
- if os.path.exists('media/IMG/rubon%s%s' % (rubric.id_rubrique, ext)):
- image_path = ['media/IMG/rubon%s%s' % (rubric.id_rubrique, ext)]
- break
- else:
- if emission.text:
- image_path = re.findall('src="/(media/IMG.*?)"', emission.text, re.DOTALL)
- elif emission.description:
- image_path = re.findall('src="/(media/IMG.*?)"', emission.description, re.DOTALL)
-
- self.set_image(emission, image_path)
-
- emission.save()
- emission.categories.clear()
- for category in rubric.categories:
- emission.categories.add(category.related_object)
- emission.save()
- return emission
-
- def get_or_create_episode(self, article, emission):
- if article.date_redac == '0000-00-00 00:00:00':
- # date_redac was used for the diffusion date, if it's
- # not set it's probably not really an episode
- if self.stats_skipped_file:
- episode_files = self.attached_documents.get(article.id_article)
- if episode_files:
- has_sound = u'♫'
- else:
- has_sound = '-'
- base_spip_edit_url = 'http://www.radiopanik.org/spip/ecrire/?exec=articles_edit&id_article='
- print >> self.stats_skipped_file, unicode('%s\t%s\t%s\t%s%s' % (
- emission.title, article.titre, has_sound,
- base_spip_edit_url, article.id_article)).encode('utf-8')
- return None
-
- possible_slugs = [article.url.lower()]
- if article.url.lower().startswith('nouvel-article'):
- possible_slugs.append(slugify(unicode(article.titre))[:40] + '-%s' % article.id_article)
-
- for slug in possible_slugs:
- try:
- episode = Episode.objects.get(slug=slug)
- break
- except Episode.DoesNotExist:
- continue
- else:
- episode = Episode()
-
- episode.slug = possible_slugs[-1]
-
- if episode.id and not self.do_updates:
- return episode
-
- episode.emission = emission
- episode.title = article.titre
- episode.description = makeHtmlFromSpip(article.descriptif,
- documents=self.documents) or None
- episode.text = makeHtmlFromSpip(article.texte,
- documents=self.documents) or None
-
- image_path = None
- for ext in ('.jpg', '.png', '.gif'):
- if os.path.exists('media/IMG/arton%s%s' % (article.id_article, ext)):
- image_path = ['media/IMG/arton%s%s' % (article.id_article, ext)]
- break
- else:
- if episode.text:
- image_path = re.findall('src="/(media/IMG.*?)"', episode.text, re.DOTALL)
- elif episode.description:
- image_path = re.findall('src="/(media/IMG.*?)"', episode.description, re.DOTALL)
-
- self.set_image(episode, image_path)
-
- episode.save()
-
- for motcle in article.mots_cles:
- episode.tags.add(motcle.lower())
-
- if not Diffusion.objects.filter(episode=episode).count():
- diffusion = Diffusion()
- diffusion.episode = episode
- try:
- diffusion.datetime = datetime.strptime(article.date_redac, '%Y-%m-%d %H:%M:%S')
- except ValueError:
- pass
- else:
- diffusion.save()
-
- return episode
-
- def set_sound_files(self, article, episode):
- if SoundFile.objects.filter(episode=episode).count():
- return # skip episodes that already have sound files
- episode_files = self.attached_documents.get(article.id_article)
- if episode_files:
- for episode_file in episode_files:
- if episode_file is None:
- continue
- if os.path.splitext(episode_file.filename)[-1] not in ('.ogg', '.mp3'):
- continue
- if not os.path.exists('media/IMG/' + episode_file.filename):
- continue
- soundfile = SoundFile()
- soundfile.episode = episode
- soundfile.podcastable = True
- soundfile.fragment = False
- soundfile.title = episode_file.title or '[pas de titre]'
- sound_path = os.path.join(settings.MEDIA_ROOT,
- get_sound_path(soundfile, episode_file.filename))
- if os.path.exists(sound_path):
- os.unlink(sound_path)
- soundfile.file = File(file('media/IMG/' + episode_file.filename))
- soundfile.save()
-
- def get_or_create_newsitem(self, breve):
- slug = breve.url.lower()
- try:
- newsitem = NewsItem.objects.get(slug=slug)
- except NewsItem.DoesNotExist:
- newsitem = NewsItem()
-
- if newsitem.id and not self.do_updates:
- return newsitem
-
- newsitem.title = breve.titre
- newsitem.slug = slug
- newsitem.text = makeHtmlFromSpip(breve.texte,
- documents=self.documents) or None
- newsitem.datetime = datetime.strptime(breve.date_heure, '%Y-%m-%d %H:%M:%S')
- for ext in ('.jpg', '.png', '.gif'):
- if os.path.exists('media/IMG/breveon%s%s' % (breve.id_breve, ext)):
- image_path = ['media/IMG/breveon%s%s' % (breve.id_breve, ext)]
- break
- else:
- image_path = re.findall('src="/(media/IMG.*?)"', newsitem.text, re.DOTALL)
- self.set_image(newsitem, image_path)
- newsitem.save()
-
- def set_image(self, object, image_path):
- if not image_path:
- return
- image_path = image_path[0]
- if object.image and os.path.basename(object.image.path) == os.path.basename(image_path):
- return
- object.image = File(file(image_path))
-
- def add_rewritemap_entries(self, spip_object, django_object):
- if isinstance(django_object, Emission):
- object_url = reverse('emission-view', kwargs={'slug': django_object.slug})
- elif isinstance(django_object, Episode):
- object_url = reverse('episode-view', kwargs={
- 'slug': django_object.slug, 'emission_slug': django_object.emission.slug})
- elif isinstance(django_object, NewsItem):
- object_url = reverse('news-view', kwargs={'slug': django_object.slug})
- else:
- return
-
- if spip_object.id[0] == '0':
- # our hack mapping some articles to newsitems
- spip_object.spip_url_object_name = 'article'
- spip_object.spip_url_marker = ''
-
- urls = []
- urls.append('%s%s' % (spip_object.spip_url_object_name, spip_object.id))
- urls.append('spip.php?%s%s' % (spip_object.spip_url_object_name, spip_object.id))
- urls.append('%s%s.html' % (spip_object.spip_url_object_name, spip_object.id))
- if spip_object.spip_url_object_name == 'article':
- urls.append(spip_object.id)
- urls.append('%s%s%s' % (spip_object.spip_url_marker, spip_object.url, spip_object.spip_url_marker))
-
- for url in urls:
- self.rewritemap.append((url, object_url))
-
- def write_rewritemap(self, rewritemap_file):
- fd = file(rewritemap_file, 'w')
- for src, dst in self.rewritemap:
- print >> fd, src, dst
- fd.close()
+++ /dev/null
-from datetime import datetime, timedelta
-
-from django.core.management.base import BaseCommand, CommandError
-from django.views.generic.dates import _date_from_string
-
-from ...utils import period_program
-
-
-class Command(BaseCommand):
- def handle(self, year, week, **options):
- date = _date_from_string(year, '%Y',
- '1', '%w',
- week, '%W')
- date = datetime(*date.timetuple()[:3])
- for entry in period_program(date, date+timedelta(days=7)):
- print entry.datetime, entry
+++ /dev/null
-from django.core.management.base import BaseCommand, CommandError
-
-from ...utils import whatsonair
-
-
-class Command(BaseCommand):
- def handle(self, *args, **options):
- onair = whatsonair()
- print 'found episode:', onair.get('episode')
- print 'found emission:', onair.get('emission')
- print 'found nonstop:', onair.get('nonstop')
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Category'
- db.create_table(u'emissions_category', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ))
- db.send_create_signal(u'emissions', ['Category'])
-
- # Adding model 'Emission'
- db.create_table(u'emissions_emission', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
- ('description', self.gf('ckeditor.fields.RichTextField')(null=True, blank=True)),
- ('text', self.gf('ckeditor.fields.RichTextField')(null=True)),
- ('archived', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ))
- db.send_create_signal(u'emissions', ['Emission'])
-
- # Adding M2M table for field categories on 'Emission'
- m2m_table_name = db.shorten_name(u'emissions_emission_categories')
- db.create_table(m2m_table_name, (
- ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('emission', models.ForeignKey(orm[u'emissions.emission'], null=False)),
- ('category', models.ForeignKey(orm[u'emissions.category'], null=False))
- ))
- db.create_unique(m2m_table_name, ['emission_id', 'category_id'])
-
- # Adding model 'Schedule'
- db.create_table(u'emissions_schedule', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('emission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.Emission'])),
- ('datetime', self.gf('django.db.models.fields.DateTimeField')()),
- ('rerun', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ))
- db.send_create_signal(u'emissions', ['Schedule'])
-
- # Adding model 'Episode'
- db.create_table(u'emissions_episode', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('emission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.Emission'])),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
- ('description', self.gf('ckeditor.fields.RichTextField')(null=True, blank=True)),
- ('text', self.gf('ckeditor.fields.RichTextField')(null=True)),
- ))
- db.send_create_signal(u'emissions', ['Episode'])
-
- # Adding model 'Diffusion'
- db.create_table(u'emissions_diffusion', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('episode', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.Episode'])),
- ('datetime', self.gf('django.db.models.fields.DateTimeField')()),
- ))
- db.send_create_signal(u'emissions', ['Diffusion'])
-
- # Adding model 'SoundFile'
- db.create_table(u'emissions_soundfile', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('episode', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.Episode'])),
- ('file', self.gf('django.db.models.fields.files.FileField')(max_length=250)),
- ('podcastable', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('fragment', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ))
- db.send_create_signal(u'emissions', ['SoundFile'])
-
-
- def backwards(self, orm):
- # Deleting model 'Category'
- db.delete_table(u'emissions_category')
-
- # Deleting model 'Emission'
- db.delete_table(u'emissions_emission')
-
- # Removing M2M table for field categories on 'Emission'
- db.delete_table(db.shorten_name(u'emissions_emission_categories'))
-
- # Deleting model 'Schedule'
- db.delete_table(u'emissions_schedule')
-
- # Deleting model 'Episode'
- db.delete_table(u'emissions_episode')
-
- # Deleting model 'Diffusion'
- db.delete_table(u'emissions_diffusion')
-
- # Deleting model 'SoundFile'
- db.delete_table(u'emissions_soundfile')
-
-
- models = {
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Emission.duration'
- db.add_column(u'emissions_emission', 'duration',
- self.gf('django.db.models.fields.IntegerField')(default=60),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Emission.duration'
- db.delete_column(u'emissions_emission', 'duration')
-
-
- models = {
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Emission.email'
- db.add_column(u'emissions_emission', 'email',
- self.gf('django.db.models.fields.EmailField')(max_length=254, null=True, blank=True),
- keep_default=False)
-
- # Adding field 'Emission.website'
- db.add_column(u'emissions_emission', 'website',
- self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Emission.email'
- db.delete_column(u'emissions_emission', 'email')
-
- # Deleting field 'Emission.website'
- db.delete_column(u'emissions_emission', 'website')
-
-
- models = {
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Episode.image'
- db.add_column(u'emissions_episode', 'image',
- self.gf('django.db.models.fields.files.ImageField')(max_length=250, null=True, blank=True),
- keep_default=False)
-
- # Adding field 'Emission.image'
- db.add_column(u'emissions_emission', 'image',
- self.gf('django.db.models.fields.files.ImageField')(max_length=250, null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Episode.image'
- db.delete_column(u'emissions_episode', 'image')
-
- # Deleting field 'Emission.image'
- db.delete_column(u'emissions_emission', 'image')
-
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Schedule.weeks'
- db.add_column(u'emissions_schedule', 'weeks',
- self.gf('django.db.models.fields.IntegerField')(default=15),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Schedule.weeks'
- db.delete_column(u'emissions_schedule', 'weeks')
-
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'NewsItem'
- db.create_table(u'emissions_newsitem', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
- ('text', self.gf('ckeditor.fields.RichTextField')()),
- ('datetime', self.gf('django.db.models.fields.DateTimeField')()),
- ('image', self.gf('django.db.models.fields.files.ImageField')(max_length=250, null=True, blank=True)),
- ('category', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.NewsCategory'], null=True)),
- ('emission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emissions.Emission'], null=True)),
- ))
- db.send_create_signal(u'emissions', ['NewsItem'])
-
- # Adding model 'NewsCategory'
- db.create_table(u'emissions_newscategory', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ))
- db.send_create_signal(u'emissions', ['NewsCategory'])
-
-
- def backwards(self, orm):
- # Deleting model 'NewsItem'
- db.delete_table(u'emissions_newsitem')
-
- # Deleting model 'NewsCategory'
- db.delete_table(u'emissions_newscategory')
-
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Episode.duration'
- db.add_column(u'emissions_episode', 'duration',
- self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
- keep_default=False)
-
- # Adding field 'Schedule.duration'
- db.add_column(u'emissions_schedule', 'duration',
- self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Episode.duration'
- db.delete_column(u'emissions_episode', 'duration')
-
- # Deleting field 'Schedule.duration'
- db.delete_column(u'emissions_schedule', 'duration')
-
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'SoundFile.title'
- db.alter_column(u'emissions_soundfile', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'NewsItem.title'
- db.alter_column(u'emissions_newsitem', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'Episode.title'
- db.alter_column(u'emissions_episode', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'Emission.title'
- db.alter_column(u'emissions_emission', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- def backwards(self, orm):
-
- # Changing field 'SoundFile.title'
- db.alter_column(u'emissions_soundfile', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
-
- # Changing field 'NewsItem.title'
- db.alter_column(u'emissions_newsitem', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
-
- # Changing field 'Episode.title'
- db.alter_column(u'emissions_episode', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
-
- # Changing field 'Emission.title'
- db.alter_column(u'emissions_emission', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'SoundFile.title'
- db.alter_column(u'emissions_soundfile', 'title', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- # Changing field 'NewsItem.title'
- db.alter_column(u'emissions_newsitem', 'title', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- # Changing field 'Episode.title'
- db.alter_column(u'emissions_episode', 'title', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- # Changing field 'Emission.title'
- db.alter_column(u'emissions_emission', 'title', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- def backwards(self, orm):
-
- # Changing field 'SoundFile.title'
- db.alter_column(u'emissions_soundfile', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'NewsItem.title'
- db.alter_column(u'emissions_newsitem', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'Episode.title'
- db.alter_column(u'emissions_episode', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'Emission.title'
- db.alter_column(u'emissions_emission', 'title', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
\ No newline at end of file
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Nonstop'
- db.create_table(u'emissions_nonstop', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('start', self.gf('django.db.models.fields.TimeField')()),
- ('end', self.gf('django.db.models.fields.TimeField')()),
- ))
- db.send_create_signal(u'emissions', ['Nonstop'])
-
-
- def backwards(self, orm):
- # Deleting model 'Nonstop'
- db.delete_table(u'emissions_nonstop')
-
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.nonstop': {
- 'Meta': {'object_name': 'Nonstop'},
- 'end': ('django.db.models.fields.TimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'start': ('django.db.models.fields.TimeField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
+++ /dev/null
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import DataMigration
-from django.db import models
-
-class Migration(DataMigration):
-
- def forwards(self, orm):
- from django.core.management import call_command
- call_command('loaddata', 'nonstop.json')
-
- def backwards(self, orm):
- pass
-
- models = {
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'emissions.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.diffusion': {
- 'Meta': {'object_name': 'Diffusion'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'emissions.emission': {
- 'Meta': {'object_name': 'Emission'},
- 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['emissions.Category']", 'symmetrical': 'False'}),
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '60'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
- },
- u'emissions.episode': {
- 'Meta': {'object_name': 'Episode'},
- 'description': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.newscategory': {
- 'Meta': {'object_name': 'NewsCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.newsitem': {
- 'Meta': {'object_name': 'NewsItem'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.NewsCategory']", 'null': 'True'}),
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'text': ('ckeditor.fields.RichTextField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'emissions.nonstop': {
- 'Meta': {'object_name': 'Nonstop'},
- 'end': ('django.db.models.fields.TimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'start': ('django.db.models.fields.TimeField', [], {}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'emissions.schedule': {
- 'Meta': {'object_name': 'Schedule'},
- 'datetime': ('django.db.models.fields.DateTimeField', [], {}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'emission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Emission']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'rerun': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'weeks': ('django.db.models.fields.IntegerField', [], {'default': '15'})
- },
- u'emissions.soundfile': {
- 'Meta': {'object_name': 'SoundFile'},
- 'episode': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['emissions.Episode']"}),
- 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '250'}),
- 'fragment': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'podcastable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
- u'taggit.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
- },
- u'taggit.taggeditem': {
- 'Meta': {'object_name': 'TaggedItem'},
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
- }
- }
-
- complete_apps = ['emissions']
- symmetrical = True
+++ /dev/null
-import datetime
-import os
-
-from django.forms import fields
-from django.core.urlresolvers import reverse
-
-from django.db import models
-
-from ckeditor.fields import RichTextField
-from taggit.managers import TaggableManager
-
-from utils import maybe_resize
-
-
-class WeekdayMixin:
- DAY_HOUR_START = 6
-
- def get_weekday(self):
- weekday = self.datetime.weekday() + 7
- if self.datetime.time() < datetime.time(self.DAY_HOUR_START, 0):
- weekday -= 1
- weekday %= 7
- return weekday
-
- def is_on_weekday(self, day): # day is [1..7]
- week_day = self.datetime.weekday()
- if self.datetime.hour < self.DAY_HOUR_START:
- week_day -= 1
- week_day = (week_day % 7) + 1
- return week_day == day
-
-
-class Category(models.Model):
- title = models.CharField(max_length=50)
-
- def sorted_emission(self):
- return self.emission_set.order_by('title')
-
- def __unicode__(self):
- return self.title
-
-
-def get_emission_image_path(instance, filename):
- return os.path.join('images', instance.slug,
- os.path.basename(filename))
-
-
-class Emission(models.Model):
- title = models.CharField(max_length=200)
- slug = models.SlugField()
- description = RichTextField(null=True, blank=True)
- text = RichTextField(null=True)
- archived = models.BooleanField(default=False)
- categories = models.ManyToManyField(Category)
-
- # XXX: languages (models.ManyToManyField(Language))
-
- duration = models.IntegerField(default=60)
-
- email = models.EmailField(max_length=254, null=True, blank=True)
- website = models.URLField(null=True, blank=True)
-
- image = models.ImageField(upload_to=get_emission_image_path, max_length=250, null=True, blank=True)
-
- def get_absolute_url(self):
- return reverse('emission-view', kwargs={'slug': str(self.slug)})
-
- def __unicode__(self):
- return self.title
-
- def save(self, *args, **kwargs):
- super(Emission, self).save(*args, **kwargs)
- if self.id is not None and self.image:
- maybe_resize(self.image.path)
-
- def get_absolute_url(self):
- return reverse('emission-view',
- kwargs={'slug': str(self.slug)})
-
- def get_schedules(self):
- return Schedule.objects.filter(emission=self).order_by('datetime')
-
- def get_sorted_emissions(self):
- return self.episode_set.select_related().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')
-
-
-
-class Schedule(models.Model, WeekdayMixin):
-
- WEEK_CHOICES = (
- (0b1111, 'Every week'),
- (0b0001, 'First week'),
- (0b0010, 'Second week'),
- (0b0100, 'Third week'),
- (0b1000, 'Fourth week'),
- (0b0101, 'First and third week'),
- (0b1010, 'Second and fourth week')
- )
- emission = models.ForeignKey('Emission', verbose_name=u'Emission')
- datetime = models.DateTimeField()
- weeks = models.IntegerField(default=15, choices=WEEK_CHOICES)
- rerun = models.BooleanField(default=False)
- duration = models.IntegerField(null=True, blank=True)
-
- @property
- def weeks_string(self):
- if self.weeks == 0b0001:
- return u'1er du mois'
- elif self.weeks == 0b0010:
- return u'2e du mois'
- elif self.weeks == 0b0100:
- return u'3e du mois'
- elif self.weeks == 0b1000:
- return u'4e du mois'
- elif self.weeks == 0b0101:
- return '1er et 3e'
- elif self.weeks == 0b1010:
- return '2e et 4e'
- return None
-
- def get_duration(self):
- if self.duration:
- return self.duration
- else:
- return self.emission.duration
-
- def match_week(self, week_no):
- if week_no == 4:
- week_no = 3
- if (self.weeks & (0b0001<<(week_no)) == 0):
- return False
- return True
-
- def matches(self, dt):
- weekday = dt.weekday()
- if dt.hour < self.DAY_HOUR_START:
- weekday -= 1
- if weekday != self.get_weekday():
- return False
- if self.weeks != 0b1111:
- week_no = (dt.day-1) // 7
- if self.match_week(week_no) is False:
- return False
- if dt.time() >= self.datetime.time() and \
- dt.time() <= (self.datetime + datetime.timedelta(minutes=self.get_duration())).time():
- return True
- return False
-
- def __unicode__(self):
- return u'%s at %s' % (self.emission.title,
- self.datetime.strftime('%a %H:%M'))
-
-
-def get_episode_image_path(instance, filename):
- return os.path.join('images', instance.emission.slug,
- os.path.basename(filename))
-
-
-class Episode(models.Model):
- emission = models.ForeignKey('Emission', verbose_name=u'Emission')
- title = models.CharField(max_length=200)
- slug = models.SlugField()
- description = RichTextField(null=True, blank=True)
- text = RichTextField(null=True)
- tags = TaggableManager(blank=True)
- duration = models.IntegerField(null=True, blank=True)
-
- image = models.ImageField(upload_to=get_episode_image_path, max_length=250, null=True, blank=True)
-
- # XXX: languages (models.ManyToManyField(Language))
-
- def __unicode__(self):
- return self.title
-
- def save(self, *args, **kwargs):
- super(Episode, self).save(*args, **kwargs)
- if self.id is not None and self.image:
- maybe_resize(self.image.path)
-
- def get_duration(self):
- if self.duration:
- return self.duration
- else:
- return self.emission.duration
-
- def get_absolute_url(self):
- return reverse('episode-view',
- kwargs={'emission_slug': str(self.emission.slug),
- 'slug': str(self.slug)})
-
- def has_sound(self):
- return (self.soundfile_set.count() > 0)
-
- _main_sound = False
-
- @property
- def main_sound(self):
- if self._main_sound is not False:
- return self._main_sound
-
- t = self.soundfile_set.exclude(podcastable=False).exclude(fragment=True)
- if t:
- self._main_sound = t[0]
- else:
- self._main_sound = None
-
- return self._main_sound
-
- @main_sound.setter
- def main_sound(self, value):
- self._main_sound = value
-
-
-class Diffusion(models.Model, WeekdayMixin):
- episode = models.ForeignKey('Episode', verbose_name=u'Episode')
- datetime = models.DateTimeField()
-
- def __unicode__(self):
- return u'%s at %02d:%02d' % (self.episode.title, self.datetime.hour,
- self.datetime.minute)
-
- def get_duration(self):
- return self.episode.get_duration()
-
-
-def get_sound_path(instance, filename):
- return os.path.join('sounds', instance.episode.emission.slug,
- os.path.basename(filename))
-
-class SoundFile(models.Model):
- episode = models.ForeignKey('Episode', verbose_name=u'Episode')
- file = models.FileField(upload_to=get_sound_path, max_length=250)
- podcastable = models.BooleanField(default=False)
- fragment = models.BooleanField(default=False)
- title = models.CharField(max_length=200)
-
- def get_format_filename(self, format):
- return '%s_%05d__%s.%s' % (
- self.episode.slug,
- self.id,
- (self.fragment and '0' or '1'),
- format)
-
- def get_format_path(self, format):
- if not self.file:
- return None
- return '%s/%s' % (os.path.dirname(self.file.path), self.get_format_filename(format))
-
- def get_format_url(self, format):
- if not self.file:
- return None
- return '%s/%s' % (os.path.dirname(self.file.url), self.get_format_filename(format))
-
-
-class NewsCategory(models.Model):
- title = models.CharField(max_length=50)
-
- def __unicode__(self):
- return self.title
-
-
-def get_newsitem_image_path(instance, filename):
- return os.path.join('images', 'news', instance.slug,
- os.path.basename(filename))
-
-
-class NewsItem(models.Model):
- title = models.CharField(max_length=200)
- slug = models.SlugField()
- text = RichTextField()
- datetime = models.DateTimeField()
- image = models.ImageField(upload_to=get_newsitem_image_path, max_length=250, null=True, blank=True)
-
- tags = TaggableManager(blank=True)
- category = models.ForeignKey('NewsCategory', verbose_name=u'Category', null=True, blank=True)
- emission = models.ForeignKey('Emission', null=True, blank=True)
-
- def __unicode__(self):
- return self.title
-
-
-class Nonstop(models.Model):
- title = models.CharField(max_length=50)
- start = models.TimeField()
- end = models.TimeField()
-
- def __unicode__(self):
- return self.title
+++ /dev/null
-import datetime
-
-from haystack import indexes
-
-from .models import Emission, Episode, NewsItem
-
-
-class EmissionIndex(indexes.SearchIndex, indexes.Indexable):
- title = indexes.CharField(model_attr='title', boost=1.5)
- text = indexes.CharField(document=True, use_template=True)
- categories = indexes.MultiValueField(faceted=True)
-
- def prepare(self, obj):
- data = super(EmissionIndex, self).prepare(obj)
- data['boost'] = 1.3
- return data
-
- def get_model(self):
- return Emission
-
- def prepare_categories(self, obj):
- return [category.title for category in obj.categories.all()]
-
-
-class EpisodeIndex(indexes.SearchIndex, indexes.Indexable):
- title = indexes.CharField(model_attr='title', boost=1.5)
- text = indexes.CharField(document=True, use_template=True)
- tags = indexes.MultiValueField(faceted=True)
-
- def get_model(self):
- return Episode
-
- def prepare_tags(self, obj):
- return [tag.name for tag in obj.tags.all()]
-
-
-class NewsItemIndex(indexes.SearchIndex, indexes.Indexable):
- title = indexes.CharField(model_attr='title', boost=1.5)
- text = indexes.CharField(document=True, use_template=True)
- tags = indexes.MultiValueField(faceted=True)
-
- def prepare(self, obj):
- data = super(NewsItemIndex, self).prepare(obj)
- today = datetime.datetime.today()
- if obj.datetime < today - datetime.timedelta(weeks=15):
- # push older news in later pages
- data['boost'] = 0.8
- elif obj.datetime > today - datetime.timedelta(weeks=3):
- # pull recent news
- data['boost'] = 1.5
- return data
-
- def get_model(self):
- return NewsItem
-
- def prepare_tags(self, obj):
- return [tag.name for tag in obj.tags.all()]
+++ /dev/null
-{% extends "base.html" %}
-
-{% block appbar %}
-<h2>Émissions</h2>
-<span><a href=".">Par ordre alphabétique</a> - <a href="days">Par jour</a> - <a href="categories">Par genre</a></span>
-{% endblock %}
-
-{% block content %}
-
-{% for category in object_list %}
-<h3>{{ category.title }}</h3>
-
-<ul class="emission-list">
-{% for emission in category.sorted_emission %}
-{% if not emission.archived %}
-<li><a href="{{ emission.slug }}/">{{ emission.title }}</a></li>
-{% endif %}
-{% endfor %}
-</ul>
-
-{% endfor %}
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block appbar %}
-<h2>Émissions</h2>
-<span><a href=".">Par ordre alphabétique</a> - <a href="days">Par jour</a> - <a href="categories">Par genre</a></span>
-{% endblock %}
-
-{% block content %}
-
-{% for day in days %}
-<h3>{{ day.datetime|date:"D" }}</h3>
-
-<ul class="emission-list">
-{% for schedule in day.schedules %}
-<li>{{ schedule.datetime|date:"H:i" }} <a href="{{ schedule.emission.slug }}/">{{ schedule.emission.title }}</a></li>
-{% endfor %}
-</ul>
-
-{% endfor %}
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block appbar %}
-<h2>{{ emission.title }}
-{% for category in emission.categories.all %}
-{% if forloop.first %} - {% endif %}
-<small><i>{{ category.title }} </i></small>
-{% endfor %}
-</h2>
-<span><a href="../">Retourner à la liste des émissions</a></span>
-{% endblock %}
-
-{% block content %}
-
-{% if emission.description %}
-<div class="description">
-{{ emission.description|safe }}
-</div>
-{% endif %}
-
-{% if emission.text %}
-{{ emission.text|safe }}
-{% endif %}
-
-<h3>Horaires</h3>
-
-<ul>
-{% for schedule in schedules %}
-<li>{{ schedule.datetime|date:"l G:i" }}
-{% if schedule.rerun %} (rediff) {% endif %}
-<a href="schedule/{{ schedule.id }}/remove" class="icon-remove-sign" title="Retirer"></a>
-</li>
-{% endfor %}
-</ul>
-
-<a id="add-schedule-link" href="#">Ajouter un horaire de diffusion</a>
-
-<form id="add-schedule-form" action="add-schedule" method="POST" style="display: none;">
-{% csrf_token %}
-{{ add_schedule_form.as_p }}
-<input type="submit" value="Ajouter cet horaire"/>
-</form>
-
-
-<h3>Épisodes</h3>
-
-<ul class="episode-list">
-{% for episode in episodes %}
-<li>{{ episode.first_diffusion|date:"d E o H:i"|lower }}
-<br/> <a href="{{ episode.slug }}/">{{ episode.title }}</a>
-{% if episode.has_sound %}<span class="icon-music"/>{%endif%}
-</li>
-{% endfor %}
-</ul>
-
-
-<a href="add">New Episode</a> - <a href="edit/">Edit</a>
-
-
-
-{% endblock %}
-
-{% block page-end %}
-<script>
-$(function() {
- $('#add-schedule-link').click(
- function() {
- $('#add-schedule-form').dialog({modal: true, title: 'Horaire', width: 'auto'});
- });
-});
-</script>
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block extrascripts %}
-<script src="{{ STATIC_URL }}ckeditor/ckeditor/ckeditor.js">
-</script>
-{% endblock %}
-
-{% block appbar %}
-<h2>{{ emission.title }}</h2>
-<span><a href="../">Retourner à l'émission</a></span>
-{% endblock %}
-
-
-{% block content %}
- <form method="post">
- <div id="form-content">
- {% csrf_token %}
- {{ form.as_p }}
- </div>
- {% block buttons %}
- <button class="enable-on-change">Modifier</button>
- {% endblock %}
- </form>
-{% endblock %}
-
+++ /dev/null
-{% extends "base.html" %}
-
-{% block appbar %}
-<h2>Émissions</h2>
-<span><a href=".">Par ordre alphabétique</a> - <a href="days">Par jour</a> - <a href="categories">Par genre</a></span>
-{% endblock %}
-
-{% block content %}
-
-<ul class="emission-list">
-{% for emission in object_list %}
-{% if not emission.archived %}
-<li><a href="{{ emission.slug }}/">{{ emission.title }}</a></li>
-{% endif %}
-{% endfor %}
-</ul>
-
-<h3>Anciennes émissions</h3>
-
-<ul class="emission-list">
-{% for emission in object_list %}
-{% if emission.archived %}
-<li><a href="{{ emission.slug }}/">{{ emission.title }}</a></li>
-{% endif %}
-{% endfor %}
-</ul>
-
-
-<a href="add">New</a>
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block appbar %}
-<h2>{{ episode.emission.title }} — {{ episode.title }}</h2>
-<span><a href="../">Retourner à l'émission</a></span>
-{% endblock %}
-
-{% block content %}
-
-<a class="big-friendly-button" href="edit/">Modifier</a>
-
-<a class="big-friendly-button" id="add-diffusion-link" href="#">Ajouter une diffusion</a>
-
-<a class="big-friendly-button" id="add-soundfile-link" href="#">Ajouter un son</a></p>
-
-
-{% if episode.description %}
-<div class="description">
-{{ episode.description|safe }}
-</div>
-{% endif %}
-
-{% if episode.text %}
-{{ episode.text|safe }}
-{% endif %}
-
-<h3>Diffusions</h3>
-
-<ul>
-{% for diffusion in diffusions %}
-<li>{{ diffusion.datetime }}
-<a href="diffusion/{{ diffusion.id }}/remove" class="icon-remove-sign" title="Retirer"></a>
-</li>
-{% endfor %}
-</ul>
-
-<form id="add-diffusion-form" action="add-diffusion" method="POST" style="display: none;">
-{% csrf_token %}
-{{ add_diffusion_form.as_p }}
-<input type="submit" value="Ajouter cet horaire"/>
-</form>
-
-
-
-<h3>Sons</h3>
-
-<table id="soundfiles">
-<thead>
-<tr>
- <th>Fichier</th>
- <th>Titre</th>
- <th>Podcastable?</th>
- <th>Fragment?</th>
-</thead>
-<tbody>
-{% for soundfile in soundfiles %}
-<tr>
-<td><a href="{{ soundfile.file.url }}">{{ soundfile.file.name }}</a></td>
-<td>{{ soundfile.title }}</td>
-<td>{{ soundfile.podcastable }}</td>
-<td>{{ soundfile.fragment }}</td>
-{% endfor %}
-</tbody>
-</table>
-
-<form id="add-soundfile-form" action="add-soundfile" method="POST" style="display: none;">
-{% csrf_token %}
-{{ add_soundfile_form.as_p }}
-<input type="submit" value="Ajouter ce son"/>
-</form>
-
-{% endblock %}
-
-
-{% block page-end %}
-<script>
-$(function() {
- $('#add-soundfile-link').click(
- function() {
- $('#add-soundfile-form').dialog({modal: true, title: 'Son', width: 'auto'});
- });
-
- $('#add-diffusion-link').click(
- function() {
- $('#add-diffusion-form').dialog({modal: true, title: 'Horaire', width: 'auto'});
- });
-});
-</script>
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block extrascripts %}
-<script src="{{ STATIC_URL }}ckeditor/ckeditor/ckeditor.js">
-</script>
-{% endblock %}
-
-{% block appbar %}
-{% if episode.id %}
-<h2>{{ episode.emission.title }} — {{ episode.title }}</h2>
-<span><a href="../">Retourner à l'épisode</a></span>
-{% else %}
-<h2>{{ emission.title }} — Nouvel épisode</h2>
-<span><a href="./">Retourner à l'émission</a></span>
-{% endif %}
-{% endblock %}
-
-
-{% block content %}
-
- <form method="post">
- <div id="form-content">
- {% csrf_token %}
- <input type="hidden" name="id_emission" value="{{ emission.id }}"/>
- {{ form.as_p }}
- </div>
- {% block buttons %}
- {% if episode.id %}
- <button>Modifier</button>
- {% else %}
- <button>Ajouter</button>
- {% endif %}
- {% endblock %}
- </form>
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block extrascripts %}
-<script src="{{ STATIC_URL }}ckeditor/ckeditor/ckeditor.js">
-</script>
-{% endblock %}
-
-{% block content %}
- <form method="post">
- <div id="form-content">
- {% csrf_token %}
- {{ form.as_p }}
- </div>
- {% block buttons %}
- <button class="enable-on-change">Modifier</button>
- {% endblock %}
- </form>
-{% endblock %}
-
+++ /dev/null
-{% load i18n %}
-<div id="fileupload" class="file-upload-widget">
- <div class="fileupload-buttonbar">
- <label class="fileinput-button">
- <input type="file" name="{{ name }}" data-url="{{ upload_url }}">
- <span class="fileinfo"><span class="filename"/></span>
- </label>
- </div>
- <div class="fileupload-content">
- <div class="fileprogress" style="display: none;">
- <div class="bar">
- Upload en cours…
- </div>
- </div>
- </div>
-</div>
+++ /dev/null
-{{ object.title }}
-
-{{ object.description|striptags }}
-
-{{ object.text|striptags }}
+++ /dev/null
-{{ object.title }}
-
-{{ object.description|striptags }}
-
-{{ object.text|striptags }}
-
-{% for tag in object.tags.all %} {{ tag.name }} {% endfor %}
+++ /dev/null
-{{ object.title }}
-
-{{ object.text|striptags }}
-
-{% if object.emission %}
-{{ object.emission.title }}
-{% endif %}
-
-{% for tag in object.tags.all %} {{ tag.name }} {% endfor %}
+++ /dev/null
-import os
-
-from django.template import Library
-
-register = Library()
-
-
-@register.filter(name='is_format_available')
-def is_available(soundfile, format='ogg'):
- if soundfile is None:
- return False
- sound_path = soundfile.get_format_path(format)
- if not sound_path:
- return False
- return os.path.exists(sound_path)
-
-@register.filter(name='format_url')
-def format_url(soundfile, format='ogg'):
- return soundfile.get_format_url(format)
+++ /dev/null
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.assertEqual(1 + 1, 2)
+++ /dev/null
-from django.conf.urls import patterns, url
-
-from .views import *
-
-urlpatterns = patterns('',
- url(r'^$', EmissionListView.as_view(), name='emission-list'),
- url(r'^categories$', CategoryListView.as_view(), name='category-list'),
- url(r'^days$', DaysView.as_view(), name='days'),
- url(r'^add$', EmissionCreateView.as_view(), name='emission-add'),
-
- url(r'^upload/(?P<transaction_id>[a-zA-Z0-9-]+)/$', UploadView.as_view(), name='upload'),
-
- url(r'^(?P<slug>[\w,-]+)/$', EmissionDetailView.as_view(), name='emission-view'),
- url(r'^(?P<slug>[\w,-]+)/edit/$', EmissionUpdateView.as_view(), name='emission-update'),
- url(r'^(?P<slug>[\w,-]+)/delete/$', EmissionDeleteView.as_view(), name='emission-delete'),
- url(r'^(?P<slug>[\w,-]+)/add-schedule$', EmissionAddScheduleView.as_view(), name='emission-add-schedule'),
-
- url(r'^(?P<emission_slug>[\w,-]+)/schedule/(?P<pk>\d+)/remove$',
- ScheduleDeleteView.as_view(), name='schedule-delete'),
-
- url(r'^(?P<emission_slug>[\w,-]+)/add$', EpisodeCreateView.as_view(), name='episode-add'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/$', EpisodeDetailView.as_view(), name='episode-view'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/edit/$', EpisodeUpdateView.as_view(), name='episode-update'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/delete/$', EpisodeDeleteView.as_view(), name='episode-delete'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/add-soundfile$',
- EpisodeAddSoundFileView.as_view(), name='episode-add-soundfile'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/add-diffusion$',
- EpisodeAddDiffusionView.as_view(), name='episode-add-diffusion'),
- url(r'^(?P<emission_slug>[\w,-]+)/(?P<slug>[\w,-]+)/diffusion/(?P<pk>\d+)/remove$',
- DiffusionDeleteView.as_view(), name='diffusion-delete'),
-
-)
+++ /dev/null
-from datetime import datetime, timedelta, time
-import os
-from PIL import Image
-
-def maybe_resize(image_path):
- if not os.path.exists(image_path):
- return
- image = Image.open(image_path)
- if max(image.size) > 1000:
- # no sense storing images that large
- factor = 1000. / max(image.size)
- image = image.resize(
- (int(image.size[0]*factor), int(image.size[1]*factor)),
- Image.ANTIALIAS)
- image.save(image_path)
-
-
-def whatsonair():
- from models import Diffusion, Schedule, Nonstop
-
- now = datetime.now()
- program = day_program(now)
- program = [x for x in program if not x.datetime > now]
-
- emission = None
- episode = None
- nonstop = None
- current_slot = None
- if program and program[-1].datetime + timedelta(minutes=program[-1].get_duration()) > now:
- current_slot = program[-1]
- if isinstance(current_slot, Schedule):
- emission = current_slot.emission
- elif isinstance(current_slot, Diffusion):
- episode = current_slot.episode
- emission = episode.emission
- else:
- for nonstop in Nonstop.objects.all():
- if (nonstop.start < nonstop.end and (
- now.time() >= nonstop.start and now.time() < nonstop.end)) or \
- (nonstop.start > nonstop.end and (
- now.time() >= nonstop.start or now.time() < nonstop.end)):
- current_slot = nonstop
- break
- else:
- nonstop = None
-
- return {'emission': emission,
- 'episode': episode,
- 'nonstop': nonstop,
- 'current_slot': current_slot}
-
-
-def period_program(date_start, date_end):
- from models import Diffusion, Schedule, Nonstop, WeekdayMixin
-
- diffusions = Diffusion.objects.select_related().filter(
- datetime__range=(date_start, date_end)).order_by('datetime')
- diffusions = [x for x in diffusions if x.datetime >= date_start and
- x.datetime < date_end]
-
- # the secondary sortkey puts schedules that happens everyweek after
- # specific ones, this will be useful later on, when multiple schedules
- # happen at the same time and we have to remove the least specific.
- period_schedules = Schedule.objects.select_related().order_by('datetime', 'weeks')
-
- program = []
- current_date = date_start
- while current_date < date_end:
- week_day = current_date.weekday()
- week_no = ((current_date.day-1) // 7)
- day_schedules = [x for x in period_schedules if x.get_weekday() == week_day and x.match_week(week_no)]
- for schedule in day_schedules:
- schedule.datetime = datetime(
- current_date.year, current_date.month, current_date.day,
- schedule.datetime.hour, schedule.datetime.minute) + \
- timedelta(days=schedule.datetime.weekday()-current_date.weekday())
- program.extend(day_schedules)
- current_date += timedelta(days=1)
-
- for i, schedule in enumerate(program):
- if schedule is None:
- continue
-
- # look for a diffusion matching this schedule
- d = [x for x in diffusions if x.datetime.timetuple()[:5] == schedule.datetime.timetuple()[:5]]
- if d:
- diffusions.remove(d[0])
- program[i] = d[0]
- for j, other_schedule in enumerate(program[i+1:]):
- # remove other emissions scheduled at the same time
- if other_schedule.datetime.timetuple()[:5] == schedule.datetime.timetuple()[:5]:
- program[i+1+j] = None
- else:
- break
-
- # here we are with remaining diffusions, those that were not overriding a
- # planned schedle
- for diffusion in diffusions:
- program = [x for x in program if x is not None]
- try:
- just_before_program = [x for x in program if x.datetime < diffusion.datetime][-1]
- new_diff_index = program.index(just_before_program)+1
- except IndexError:
- # nothing before
- new_diff_index = 0
- program.insert(new_diff_index, diffusion)
-
- # cut (or even remove) programs that started earlier but continued over
- # this program start time
- i = new_diff_index
- while i > 0:
- previous = program[i-1]
- previous_endtime = previous.datetime + timedelta(minutes=previous.get_duration())
- if previous_endtime > diffusion.datetime:
- previous.duration = (diffusion.datetime - previous.datetime).seconds / 60
- if previous.duration <= 0:
- program[i-1] = None
- i -= 1
-
- # push back (or remove) programs that started before this program ends
- # (this may be unnecessary as next step does that again for all
- # programs)
- diffusion_endtime = diffusion.datetime + timedelta(minutes=diffusion.get_duration())
- i = new_diff_index
- while i < len(program)-1:
- next_prog = program[i+1]
- if next_prog.datetime < diffusion_endtime:
- diff = diffusion_endtime - next_prog.datetime
- if (diff.seconds/60) > next_prog.get_duration():
- program[i+1] = None
- else:
- next_prog.datetime = diffusion_endtime
- next_prog.duration = next_prog.get_duration() - (diff.seconds/60)
- i += 1
-
- # remove overlapping programs
- program = [x for x in program if x is not None]
- for i, slot in enumerate(program):
- if slot is None:
- continue
-
- slot_end = slot.datetime + timedelta(minutes=slot.get_duration())
-
- j = i+1
- while j < len(program)-1:
- if program[j]:
- if slot_end > program[j].datetime:
- program[j] = None
- j += 1
-
- program = [x for x in program if x is not None]
-
- # last step is adding nonstop zones between slots
- nonstops = Nonstop.objects.all()
-
- class NonstopSlot(WeekdayMixin):
- def __init__(self, start, end):
- self.datetime = None
- labels = []
- for nonstop in nonstops:
- nonstop_day_start = start.replace(hour=nonstop.start.hour, minute=nonstop.start.minute)
- nonstop_day_end = start.replace(hour=nonstop.end.hour, minute=nonstop.end.minute)
- if nonstop.end < nonstop.start:
- if start.time() < nonstop.end:
- nonstop_day_start -= timedelta(days=1)
- else:
- nonstop_day_end += timedelta(days=1)
-
- if nonstop_day_start < end and nonstop_day_end > start:
- if self.datetime is None:
- self.datetime = nonstop_day_end
- labels.append(nonstop.title)
- self.label = u', '.join(labels)
-
- def __repr__(self):
- return repr(self.label)
-
- def get_duration(self):
- # fake duration
- return 0
-
-
- first_day_start = datetime(*date_start.replace(hour=6, minute=0).timetuple()[:5])
- last_day_end = datetime(*date_end.replace(hour=5, minute=0).timetuple()[:5])
-
- program.insert(0, NonstopSlot(first_day_start, program[0].datetime))
-
- i = 0
- while i < len(program)-1:
- slot = program[i]
- if not isinstance(slot, NonstopSlot):
- slot_end = slot.datetime + timedelta(minutes=slot.get_duration())
- next_slot = program[i+1]
-
- if slot_end < next_slot.datetime:
- next_day_start = next_slot.datetime.replace(hour=5, minute=0)
- if slot_end < next_day_start and next_slot.datetime > next_day_start:
- program[i+1:i+1] = [NonstopSlot(slot_end, next_day_start),
- NonstopSlot(next_day_start, next_slot.datetime)]
- else:
- program[i+1:i+1] = [NonstopSlot(slot_end, next_slot.datetime)]
-
- i += 1
-
- program.append(NonstopSlot(program[-1].datetime, last_day_end))
-
- return program
-
-def day_program(date):
- date_start = datetime(*date.timetuple()[:3])
- date_end = date_start + timedelta(days=1)
- return period_program(date_start, date_end)
+++ /dev/null
-import datetime
-import os
-
-from django.core.files.storage import DefaultStorage
-from django.http import HttpResponse, Http404
-from django.core.urlresolvers import reverse, reverse_lazy
-from django.utils import simplejson
-
-from django.views.decorators.csrf import csrf_exempt
-from django.views.generic.base import View, TemplateView, RedirectView
-from django.views.generic.edit import CreateView, UpdateView, DeleteView
-from django.views.generic.list import ListView
-from django.views.generic.detail import DetailView
-
-import haystack.views
-
-from .models import Emission, Episode, Diffusion, Category, Schedule, SoundFile
-from .forms import EmissionForm, EpisodeForm, EpisodeNewForm, ScheduleForm, \
- DiffusionForm, SoundFileForm
-
-
-__all__ = ['EmissionListView', 'EmissionDetailView', 'EmissionCreateView',
- 'EmissionUpdateView', 'EmissionDeleteView',
- 'EpisodeCreateView', 'EpisodeDetailView', 'EpisodeUpdateView',
- 'EpisodeDeleteView', 'EmissionAddScheduleView',
- 'ScheduleDeleteView', 'CategoryListView', 'DaysView',
- 'UploadView', 'EpisodeAddSoundFileView',
- 'EpisodeAddDiffusionView', 'DiffusionDeleteView']
-
-
-class EmissionListView(ListView):
- model = Emission
-
- def get_queryset(self):
- return Emission.objects.order_by('title')
-
-
-class CategoryListView(ListView):
- model = Category
-
- def get_queryset(self):
- return Category.objects.order_by('title')
-
-
-class EmissionDetailView(DetailView):
- model = Emission
-
- def get_context_data(self, **kwargs):
- context = super(EmissionDetailView, self).get_context_data(**kwargs)
- context['add_schedule_form'] = ScheduleForm(initial={'emission': self.object})
- context['schedules'] = Schedule.objects.filter(emission=self.object).order_by('datetime')
-
- # get all episodes, with an additional attribute to get the date of
- # their first diffusion
- context['episodes'] = \
- Episode.objects.select_related().filter(emission=self.object
- ).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')
-
- # get all related soundfiles in a single query
- soundfiles = {}
- for soundfile in SoundFile.objects.filter(podcastable=True,
- fragment=False, episode__emission=self.object):
- soundfiles[soundfile.episode_id] = soundfile
-
- # replace dynamic property by a static attribute, to avoid database
- # lookups
- for episode in context['episodes']:
- episode.main_sound = soundfiles.get(episode.id)
-
- return context
-
-
-class EmissionCreateView(CreateView):
- form_class = EmissionForm
- model = Emission
-
- success_url = reverse_lazy('emission-list')
-
-
-class EmissionUpdateView(UpdateView):
- form_class = EmissionForm
- model = Emission
-
-
-class EmissionDeleteView(DeleteView):
- model = Emission
-
-
-class EpisodeCreateView(CreateView):
- model = Episode
- form_class = EpisodeNewForm
-
- def get_initial(self):
- initial = super(EpisodeCreateView, self).get_initial()
- initial['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
- initial['duration'] = initial['emission'].duration
- return initial
-
- def get_context_data(self, **kwargs):
- context = super(EpisodeCreateView, self).get_context_data(**kwargs)
- context['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
- return context
-
- def get_success_url(self):
- return self.object.get_absolute_url()
-
-
-class EpisodeDetailView(DetailView):
- model = Episode
-
- def get_context_data(self, **kwargs):
- context = super(EpisodeDetailView, self).get_context_data(**kwargs)
- context['diffusions'] = Diffusion.objects.filter(episode=self.object.id)
- context['soundfiles'] = SoundFile.objects.filter(episode=self.object.id)
- context['add_soundfile_form'] = SoundFileForm(initial={'episode': self.object})
- context['add_diffusion_form'] = DiffusionForm(initial={'episode': self.object})
- context['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
- # get all episodes, with an additional attribute to get the date of
- # their first diffusion
- context['episodes'] = \
- Episode.objects.filter(emission=context['emission']
- ).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')
-
- # get all related soundfiles in a single query
- soundfiles = {}
- for soundfile in SoundFile.objects.filter(podcastable=True,
- fragment=False, episode__emission=self.object):
- soundfiles[soundfile.episode_id] = soundfile
-
- # replace dynamic property by a static attribute, to avoid database
- # lookups
- for episode in context['episodes']:
- episode.main_sound = soundfiles.get(episode.id)
- return context
-
-
-class EpisodeUpdateView(UpdateView):
- form_class = EpisodeForm
- model = Episode
-
-
-class EpisodeDeleteView(DeleteView):
- model = Episode
-
-
-class EmissionAddScheduleView(CreateView):
- form_class = ScheduleForm
- model = Schedule
-
- def get_success_url(self):
- return self.object.emission.get_absolute_url()
-
-
-class ScheduleDeleteView(RedirectView):
- def get_redirect_url(self, emission_slug, pk):
- Schedule.objects.filter(id=pk).delete()
- return reverse('emission-view', kwargs={'slug': str(emission_slug)})
-
-
-class DaysView(TemplateView):
- template_name = 'emissions/days.html'
-
- def get_context_data(self, **kwargs):
- context = super(DaysView, self).get_context_data(**kwargs)
- schedules = Schedule.objects.all().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.datetime(2007, 1, day+1)})
- context['days'] = days
- return context
-
-class JSONResponse(HttpResponse):
- """JSON response class."""
- def __init__(self, obj='', json_opts={}, mimetype='application/json', *args, **kwargs):
- content = simplejson.dumps(obj, **json_opts)
- super(JSONResponse,self).__init__(content, mimetype, *args, **kwargs)
-
-
-class UploadView(View):
-
- def response_mimetype(self, request):
- if 'application/json' in request.META['HTTP_ACCEPT']:
- return 'application/json'
- else:
- return 'text/plain'
-
- @csrf_exempt
- def post(self, request, transaction_id):
- storage = DefaultStorage()
- max_filename_length = 256
- url = reverse('upload', kwargs={'transaction_id': transaction_id})
- if request.FILES is None:
- response = JSONResponse({}, {}, self.response_mimetype(request))
- response['Content-Disposition'] = 'inline; filename=files.json'
- return response
- data = []
- for uploaded_file in request.FILES.values():
- path = os.path.join('upload', str(transaction_id), uploaded_file.name)
- filename = storage.save(path, uploaded_file)
- url = '%s%s' % (url, os.path.basename(filename))
- data.append({'name': uploaded_file.name, 'size': uploaded_file.size, 'url': url})
- response = JSONResponse(data, {}, self.response_mimetype(request))
- response['Content-Disposition'] = 'inline; filename=files.json'
- return response
-
-
-class EpisodeAddSoundFileView(CreateView):
- form_class = SoundFileForm
- model = SoundFile
-
- def get_success_url(self):
- return self.object.episode.get_absolute_url()
-
-
-class EpisodeAddDiffusionView(CreateView):
- form_class = DiffusionForm
- model = Diffusion
-
- def get_success_url(self):
- return self.object.episode.get_absolute_url()
-
-
-class DiffusionDeleteView(RedirectView):
- def get_redirect_url(self, emission_slug, slug, pk):
- Diffusion.objects.filter(id=pk).delete()
- return reverse('episode-view', kwargs={'emission_slug': str(emission_slug),
- 'slug': str(slug)})
-
-
-class FacetedSearchView(haystack.views.FacetedSearchView):
- def extra_context(self):
- context = super(FacetedSearchView, self).extra_context()
- context['selected_categories'] = [
- x.split(':', 1)[1] for x in self.request.GET.getlist('selected_facets')
- if x.startswith('categories_exact')]
- context['selected_tags'] = [
- x.split(':', 1)[1] for x in self.request.GET.getlist('selected_facets')
- if x.startswith('tags_exact')]
- return context
'jquery',
'datetimewidget',
'django_bootstrap_staticfiles',
- 'panikdb.emissions',
+ 'emissions',
'panikdb.aa',
)
from haystack.query import SearchQuerySet
from emissions.views import FacetedSearchView
-from .emissions.urls import urlpatterns as emissions_urlpatterns
+from emissions.urls import urlpatterns as emissions_urlpatterns
from urls_utils import decorated_includes
django-jquery
django-datetime-widget
django-bootstrap-staticfiles
+git+http://git.domainepublic.net/git/django-panik-emissions.git