This commit is contained in:
bkfox 2015-10-03 14:58:44 +02:00
parent f9d2d47ee6
commit 1a5dcc3eb9
45 changed files with 380 additions and 321 deletions

0
programs/__init__.py → aircox_cms/__init__.py Executable file → Normal file
View File

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import taggit.managers
import django.db.models.deletion
import datetime
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('taggit', '0002_auto_20150616_2121'),
]
operations = [
migrations.CreateModel(
name='Article',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('date', models.DateTimeField(default=datetime.datetime.now, verbose_name='date')),
('published', models.BooleanField(default=True, verbose_name='public')),
('title', models.CharField(verbose_name='titre', max_length=128)),
('content', models.TextField(null=True, blank=True, verbose_name='description')),
('image', models.ImageField(null=True, blank=True, upload_to='')),
('static_page', models.BooleanField(default=False, verbose_name='page statique')),
('focus', models.BooleanField(default=False, verbose_name="l'article est épinglé")),
('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, blank=True, verbose_name='auteur')),
('tags', taggit.managers.TaggableManager(through='taggit.TaggedItem', to='taggit.Tag', blank=True, help_text='A comma-separated list of tags.', verbose_name='mots-clés')),
],
options={
'verbose_name': 'Article',
'verbose_name_plural': 'Articles',
},
),
migrations.CreateModel(
name='Thread',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('post_id', models.PositiveIntegerField()),
('post_type', models.ForeignKey(to='contenttypes.ContentType')),
],
),
migrations.AddField(
model_name='article',
name='thread',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, null=True, help_text='the publication is posted on this thread', blank=True, to='aircox_cms.Thread'),
),
]

View File

@ -0,0 +1,10 @@
body { padding: 0; margin: 0; }
nav.menu_top {
width: 100%
position: absolute;
border-bottom: 1px grey solid;
}

View File

@ -1,5 +1,14 @@
{% load staticfiles %}
<html> <html>
<head> <head>
{# FIXME: page tags #}
<meta charset="utf-8">
<meta name="application-name" content="aircox-cms">
<meta name="description" content="{{ website.description }}">
<meta name="keywords" content="{{ website.tags }}">
<link rel="stylesheet" href="{% static "aircox_aircox_cms/styles.css" %}" type="text/css">
<title>{{ website.name }} {% if title %}- {{ title }} {% endif %}</title> <title>{{ website.name }} {% if title %}- {{ title }} {% endif %}</title>
</head> </head>
<body> <body>
@ -35,6 +44,10 @@
{% endblock %} {% endblock %}
</div> </div>
</main> </main>
{% if menus.right %}
{{ menus.right|safe }}
{% endif %}
</div> </div>
{% block footer %} {% block footer %}
@ -44,6 +57,10 @@
</footer> </footer>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% if menus.bottom %}
{{ menus.bottom|safe }}
{% endif %}
</body> </body>
</html> </html>

View File

@ -1,4 +1,4 @@
{% extends embed|yesno:"cms/base_content.html,cms/base_site.html" %} {% extends embed|yesno:"aircox_cms/base_content.html,aircox_cms/base_site.html" %}
{% block title %} {% block title %}
{{ object.title }} {{ object.title }}

View File

@ -1,4 +1,4 @@
{% extends embed|yesno:"cms/base_content.html,cms/base_site.html" %} {% extends embed|yesno:"aircox_cms/base_content.html,aircox_cms/base_site.html" %}
{% load i18n %} {% load i18n %}
{% load thumbnail %} {% load thumbnail %}

View File

@ -1,4 +1,4 @@
{% extends "cms/section.html" %} {% extends "aircox_cms/section.html" %}
{% load thumbnail %} {% load thumbnail %}

View File

@ -0,0 +1,6 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //

0
programs/tests.py → aircox_cms/tests.py Executable file → Normal file
View File

View File

@ -5,7 +5,7 @@ from django.views.generic.base import View, TemplateResponseMixin
from django.core import serializers from django.core import serializers
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
import cms.routes as routes import aircox_cms.routes as routes
class PostBaseView: class PostBaseView:
@ -67,7 +67,7 @@ class PostListView (PostBaseView, ListView):
return return
self.__dict__.update(query) self.__dict__.update(query)
template_name = 'cms/list.html' template_name = 'aircox_cms/list.html'
allow_empty = True allow_empty = True
route = None route = None
@ -127,7 +127,7 @@ class PostDetailView (DetailView, PostBaseView):
""" """
Detail view for posts and children Detail view for posts and children
""" """
template_name = 'cms/detail.html' template_name = 'aircox_cms/detail.html'
sections = [] sections = []
@ -135,9 +135,12 @@ class PostDetailView (DetailView, PostBaseView):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.sections = sections or [] self.sections = sections or []
def get_queryset (self, **kwargs): def get_queryset (self):
if self.request.GET.get('embed'):
self.embed = True
if self.model: if self.model:
return super().get_queryset(**kwargs).filter(published = True) return super().get_queryset().filter(published = True)
return [] return []
def get_object (self, **kwargs): def get_object (self, **kwargs):
@ -193,7 +196,7 @@ class ViewSet:
class Menu (View): class Menu (View):
template_name = 'cms/menu.html' template_name = 'aircox_cms/menu.html'
name = '' name = ''
enabled = True enabled = True
@ -227,7 +230,7 @@ class Section (View):
Base class for sections. Sections are view that can be used in detail view Base class for sections. Sections are view that can be used in detail view
in order to have extra content about a post. in order to have extra content about a post.
""" """
template_name = 'cms/section.html' template_name = 'aircox_cms/section.html'
require_object = False require_object = False
object = None object = None
classes = '' classes = ''
@ -271,7 +274,7 @@ class ListSection (Section):
use_icons = True use_icons = True
icon_size = '32x32' icon_size = '32x32'
template_name = 'cms/section_list.html' template_name = 'aircox_cms/section_list.html'
def get_object_list (self): def get_object_list (self):
return [] return []

View File

@ -1,8 +1,11 @@
import cms.routes as routes import aircox_cms.routes as routes
class Website: class Website:
name = '' name = ''
domain = '' domain = ''
description = 'An aircox website' # public description (used in meta info)
tags = 'aircox,radio,music' # public keywords (used in meta info)
logo = None logo = None
menus = None menus = None
router = None router = None

View File

@ -7,8 +7,8 @@ from django.db import models
from suit.admin import SortableTabularInline, SortableModelAdmin from suit.admin import SortableTabularInline, SortableModelAdmin
from autocomplete_light.contrib.taggit_field import TaggitWidget, TaggitField from autocomplete_light.contrib.taggit_field import TaggitWidget, TaggitField
from programs.forms import * from aircox_programs.forms import *
from programs.models import * from aircox_programs.models import *
# #

View File

@ -1,5 +1,5 @@
import autocomplete_light.shortcuts as al import autocomplete_light.shortcuts as al
from programs.models import * from aircox_programs.models import *
from taggit.models import Tag from taggit.models import Tag
al.register(Tag) al.register(Tag)

View File

@ -4,7 +4,7 @@ from django.contrib.admin import widgets
import autocomplete_light.shortcuts as al import autocomplete_light.shortcuts as al
from autocomplete_light.contrib.taggit_field import TaggitWidget from autocomplete_light.contrib.taggit_field import TaggitWidget
from programs.models import * from aircox_programs.models import *
class TrackForm (forms.ModelForm): class TrackForm (forms.ModelForm):

View File

@ -17,7 +17,7 @@ from the (given) month and later.
from argparse import RawTextHelpFormatter from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone as tz from django.utils import timezone as tz
from programs.models import * from aircox_programs.models import *
class Actions: class Actions:

View File

@ -3,7 +3,7 @@ import json
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone from django.utils import timezone
import programs.models as models import aircox_programs.models as models
class Model: class Model:

View File

@ -20,8 +20,8 @@ from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone from django.utils import timezone
from programs.models import * from aircox_programs.models import *
import programs.settings as settings import aircox_programs.settings as settings
class Command (BaseCommand): class Command (BaseCommand):

View File

@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
('taggit', '0002_auto_20150616_2121'),
]
operations = [
migrations.CreateModel(
name='Diffusion',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('type', models.SmallIntegerField(choices=[(0, 'default'), (4, 'stop'), (1, 'unconfirmed'), (2, 'cancel')], verbose_name='type')),
('date', models.DateTimeField(verbose_name='start of the diffusion')),
],
options={
'verbose_name': 'Diffusion',
'verbose_name_plural': 'Diffusions',
},
),
migrations.CreateModel(
name='Episode',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(verbose_name='nom', max_length=128)),
],
options={
'verbose_name': 'Épisode',
'verbose_name_plural': 'Épisodes',
},
),
migrations.CreateModel(
name='Program',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(verbose_name='nom', max_length=128)),
('active', models.BooleanField(default=True, help_text='if not set this program is no longer active', verbose_name='inactive')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Schedule',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('date', models.DateTimeField(verbose_name='date')),
('duration', models.TimeField(verbose_name='durée')),
('frequency', models.SmallIntegerField(choices=[(4, 'third'), (32, 'one on two'), (10, 'second and fourth'), (5, 'first and third'), (31, 'every'), (2, 'second'), (1, 'first'), (16, 'last'), (8, 'fourth')], verbose_name='fréquence')),
('program', models.ForeignKey(to='aircox_programs.Program', null=True, blank=True)),
('rerun', models.ForeignKey(to='aircox_programs.Schedule', null=True, help_text='Schedule of a rerun of this one', blank=True, verbose_name='rediffusion')),
],
options={
'verbose_name': 'Schedule',
'verbose_name_plural': 'Schedules',
},
),
migrations.CreateModel(
name='Sound',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(verbose_name='nom', max_length=128)),
('path', models.FilePathField(recursive=True, match='*(.ogg|.flac|.wav|.mp3|.opus)$', path='/media/data/courants/code/aircox/static/media/programs', null=True, blank=True, verbose_name='fichier')),
('embed', models.TextField(null=True, blank=True, help_text='if set, consider the sound podcastable', verbose_name='embed HTML code from external website')),
('duration', models.TimeField(null=True, blank=True, verbose_name='durée')),
('public', models.BooleanField(default=False, help_text='the element is public', verbose_name='public')),
('fragment', models.BooleanField(default=False, help_text='the file is a cut', verbose_name='son incomplet')),
('removed', models.BooleanField(default=False, help_text='this sound has been removed from filesystem')),
],
options={
'verbose_name': 'Sound',
'verbose_name_plural': 'Sounds',
},
),
migrations.CreateModel(
name='Stream',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(null=True, blank=True, verbose_name='nom', max_length=32)),
('public', models.BooleanField(default=True, help_text='program list is public', verbose_name='public')),
('type', models.SmallIntegerField(choices=[(1, 'schedule'), (0, 'random')], verbose_name='type')),
('priority', models.SmallIntegerField(default=0, help_text='priority of the stream', verbose_name='priority')),
],
),
migrations.CreateModel(
name='Track',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(verbose_name='nom', max_length=128)),
('artist', models.CharField(verbose_name='artiste', max_length=128)),
('position', models.SmallIntegerField(default=0, help_text='position in the playlist')),
('episode', models.ForeignKey(to='aircox_programs.Episode')),
('tags', taggit.managers.TaggableManager(through='taggit.TaggedItem', to='taggit.Tag', blank=True, help_text='A comma-separated list of tags.', verbose_name='mots-clés')),
],
options={
'verbose_name': 'Track',
'verbose_name_plural': 'Tracks',
},
),
migrations.AddField(
model_name='program',
name='stream',
field=models.ForeignKey(to='aircox_programs.Stream', verbose_name='stream'),
),
migrations.AddField(
model_name='episode',
name='program',
field=models.ForeignKey(to='aircox_programs.Program', help_text='parent program', verbose_name='program'),
),
migrations.AddField(
model_name='episode',
name='sounds',
field=models.ManyToManyField(to='aircox_programs.Sound', blank=True, verbose_name='sounds'),
),
migrations.AddField(
model_name='diffusion',
name='episode',
field=models.ForeignKey(to='aircox_programs.Episode', null=True, blank=True, verbose_name='épisode'),
),
migrations.AddField(
model_name='diffusion',
name='program',
field=models.ForeignKey(to='aircox_programs.Program', verbose_name='program'),
),
migrations.AddField(
model_name='diffusion',
name='stream',
field=models.ForeignKey(default=0, help_text='stream id on which the diffusion happens', to='aircox_programs.Stream', verbose_name='stream'),
),
]

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('aircox_programs', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='diffusion',
name='type',
field=models.SmallIntegerField(choices=[(4, 'stop'), (2, 'cancel'), (1, 'unconfirmed'), (0, 'default')], verbose_name='type'),
),
migrations.AlterField(
model_name='schedule',
name='frequency',
field=models.SmallIntegerField(choices=[(31, 'every'), (8, 'fourth'), (5, 'first and third'), (10, 'second and fourth'), (16, 'last'), (32, 'one on two'), (4, 'third'), (1, 'first'), (2, 'second')], verbose_name='fréquence'),
),
]

View File

View File

@ -8,7 +8,7 @@ from django.utils.html import strip_tags
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
import programs.settings as settings import aircox_programs.settings as settings
def date_or_default (date, date_only = False): def date_or_default (date, date_only = False):

3
aircox_programs/tests.py Executable file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
aircox_programs/utils.py Normal file
View File

@ -0,0 +1,6 @@
def ensure_list (value):
if type(value) in (list, set, tuple):
return value
return [value]

90
aircox_programs/views.py Executable file
View File

@ -0,0 +1,90 @@
from django.db import models
from django.shortcuts import render
from django.core.serializers.json import DjangoJSONEncoder
from django.utils import timezone, dateformat
from django.views.generic import ListView
from django.views.generic import DetailView
from django.utils.translation import ugettext as _, ugettext_lazy
from aircox_programs.models import *
import aircox_programs.settings
import aircox_programs.utils
class ListQueries:
@staticmethod
def search (qs, q):
qs = qs.filter(tags__slug__in = re.compile(r'(\s|\+)+').split(q)) | \
qs.filter(title__icontains = q) | \
qs.filter(subtitle__icontains = q) | \
qs.filter(content__icontains = q)
qs.distinct()
return qs
@staticmethod
def thread (qs, q):
return qs.filter(parent = q)
@staticmethod
def next (qs, q):
qs = qs.filter(date__gte = timezone.now())
if q:
qs = qs.filter(parent = q)
return qs
@staticmethod
def prev (qs, q):
qs = qs.filter(date__lte = timezone.now())
if q:
qs = qs.filter(parent = q)
return qs
@staticmethod
def date (qs, q):
if not q:
q = timezone.datetime.today()
if type(q) is str:
q = timezone.datetime.strptime(q, '%Y/%m/%d').date()
return qs.filter(date__startswith = q)
class Diffusion:
@staticmethod
def episode (qs, q):
return qs.filter(episode = q)
@staticmethod
def program (qs, q):
return qs.filter(program = q)
class ListQuery:
model = None
qs = None
def __init__ (self, model, *kwargs):
self.model = model
self.__dict__.update(kwargs)
def get_queryset (self, by, q):
qs = model.objects.all()
if model._meta.get_field_by_name('public'):
qs = qs.filter(public = True)
# run query set
queries = Queries.__dict__.get(self.model) or Queries
filter = queries.__dict__.get(by)
if filter:
qs = filter(qs, q)
# order
if self.sort == 'asc':
qs = qs.order_by('date', 'id')
else:
qs = qs.order_by('-date', '-id')
# exclude
qs = qs.exclude(id = exclude)
return qs

View File

@ -1,49 +0,0 @@
This application defines all base classes for the aircox platform. This includes:
* **Metadata**: generic class that contains metadata
* **Publication**: generic class for models that can be publicated
* **Track**: informations on a track in a playlist
* **SoundFile**: informations on a sound (podcast)
* **Schedule**: schedule informations for programs
* **Article**: simple article
* **Program**: radio program
* **Episode**: occurence of a radio program
* **Event**: log info on what has been or what should be played
# Program
Each program has a directory in **AIRCOX_PROGRAMS_DATA**; For each, subdir:
* **public**: public sound files and data (accessible from the website)
* **private**: private sound files and data
* **podcasts**: podcasts that can be upload to external plateforms
# Event
Event have a double purpose:
- log played sounds
- plannify diffusions
# manage.py schedule
Return the next songs to be played and the schedule and the programmed emissions
# manage.py monitor
The manage.py has a command **monitor** that:
* check for new sound files
* stat the sound files
* match sound files against episodes and eventually program them
* upload public podcasts to mixcloud if required
The command will try to match file name against a planified episode by detecting
a date (ISO 8601 date notation YYYY-MM-DD or YYYYMMDD) as name prefix
Tags set:
* **incorrect**: the sound is not correct for diffusion (TODO: parameters)

View File

@ -1,237 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-02 17:05+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: models.py:51
msgid "ponctual"
msgstr ""
#: models.py:52
msgid "every week"
msgstr "toutes les semaines"
#: models.py:53
msgid "first week"
msgstr "1<sup>ère</sup> semaine du mois"
#: models.py:54
msgid "second week"
msgstr "2<sup>ème</sup> semaine du mois"
#: models.py:55
msgid "third week"
msgstr "3<sup>ème</sup> semaine du mois"
#: models.py:56
msgid "fourth week"
msgstr "4<sup>ème</sup> semaine du mois"
#: models.py:57
msgid "first and third"
msgstr "la 1<sup>ère</sup> et 2<sup>ème</sup> semaine du mois"
#: models.py:58
msgid "second and fourth"
msgstr "la 2<sup>ème</sup> et 4<sup>ème</sup> semaine du mois"
#: models.py:59
msgid "one week on two"
msgstr "une semaine sur deux"
#: models.py:74
msgid "author"
msgstr "auteur"
#: models.py:78 models.py:568
msgid "date"
msgstr "date"
#: models.py:81 models.py:332
msgid "title"
msgstr "titre"
#: models.py:89 models.py:565
msgid "meta"
msgstr "metadonnées"
#: models.py:93
msgid "tags"
msgstr "mots-clés"
#: models.py:125
msgid "subtitle"
msgstr "sous-titre"
#: models.py:129
msgid "image"
msgstr "image"
#: models.py:133
msgid "content"
msgstr "contenu"
#: models.py:136 models.py:575
msgid "status"
msgstr "statut"
#: models.py:140
msgid "enable comments"
msgstr "activer les commentaires"
#: models.py:328
msgid "artist"
msgstr "artiste"
#: models.py:335
msgid "version"
msgstr "version"
#: models.py:338
msgid "additional informations on that track"
msgstr "informations supplémentaires sur cette piste"
#: models.py:343
msgid "by"
msgstr "par"
#: models.py:348
msgid "track"
msgstr "piste"
#: models.py:349
msgid "tracks"
msgstr "pistes"
#: models.py:356
msgid "file"
msgstr "fichier"
#: models.py:360 models.py:380 models.py:570
msgid "duration"
msgstr "durée"
#: models.py:364
msgid "podcastable"
msgstr "peut être podcasté"
#: models.py:366
msgid "if checked, the file can be podcasted"
msgstr "si coché, le fichier peut être podcasté"
#: models.py:368
msgid "incomplete sound"
msgstr "son incomplet"
#: models.py:370
msgid "the file has been cut"
msgstr "le fichier a été monté"
#: models.py:378
msgid "schedule"
msgstr "horaire"
#: models.py:379
msgid "frequency"
msgstr "fréquence"
#: models.py:381 models.py:452
msgid "rerun"
msgstr "rediffusion"
#: models.py:464 models.py:485 models.py:524
msgid "parent"
msgstr "parent"
#: models.py:468
msgid "static page"
msgstr "page statique"
#: models.py:471
msgid "article is focus"
msgstr "l'article est épinglé"
#: models.py:477
msgid "Article"
msgstr "Article"
#: models.py:478
msgid "Articles"
msgstr "Articles"
#: models.py:490
msgid "email"
msgstr "email"
#: models.py:495
msgid "website"
msgstr "site"
#: models.py:499
msgid "tag"
msgstr "mot-clé"
#: models.py:501
msgid "used in articles to refer to it"
msgstr "utilisé par les articles pour y faire référence"
#: models.py:510
msgid "Emission"
msgstr "Émission"
#: models.py:511
msgid "Emissions"
msgstr "Émissions"
#: models.py:529
msgid "podcast file"
msgstr "fichier de podcast"
#: models.py:534
msgid "playlist"
msgstr "playlist"
#: models.py:543
#, python-format
msgid "An unknown name for this episode of %s"
msgstr "Cette épisode de %s n'a pas encore de nom"
#: models.py:551
msgid "Episode"
msgstr "Épisode"
#: models.py:552
msgid "Episodes"
msgstr "Épisodes"
#: models.py:561
msgid "episode"
msgstr "épisode"
#: models.py:573
msgid "this is just indicative"
msgstr "juste indicatif"
#: models.py:578
msgid "canceled"
msgstr "annulé"
#~ msgid "third %s of the month"
#~ msgstr "le troisième %s du mois"
#~ msgid "fourth %s of the month"
#~ msgstr "le quatrième %s du mois"

View File

@ -1,5 +0,0 @@
Django>=1.9.0
django-taggit>=0.12.1
django-autocomplete-light>=2.2.5
django-suit>=0.2.14

View File

@ -4,7 +4,7 @@ from django.contrib import admin
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
from django.contrib.contenttypes.admin import GenericStackedInline from django.contrib.contenttypes.admin import GenericStackedInline
import programs.models as programs import aircox_programs.models as programs
from website.models import * from website.models import *

View File

@ -1,7 +1,7 @@
from django.db import models from django.db import models
from cms.models import RelatedPost from aircox_cms.models import RelatedPost
import programs.models as programs import aircox_programs.models as programs
class Program (RelatedPost): class Program (RelatedPost):
class Relation: class Relation:

View File

@ -3,10 +3,10 @@ from django.conf.urls import url, include
from website.models import * from website.models import *
from website.views import * from website.views import *
from cms.models import Article from aircox_cms.models import Article
from cms.views import ViewSet, Menu, Section from aircox_cms.views import ViewSet, Menu, Section
from cms.routes import * from aircox_cms.routes import *
from cms.website import Website from aircox_cms.website import Website
class ProgramSet (ViewSet): class ProgramSet (ViewSet):
model = Program model = Program

View File

@ -5,8 +5,8 @@ from django.views.generic import DetailView
from django.core import serializers from django.core import serializers
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
import programs.models as programs import aircox_programs.models as programs
from cms.views import ListSection from aircox_cms.views import ListSection
class PlaylistSection (ListSection): class PlaylistSection (ListSection):