--- /dev/null
+# trivial: apply black
+f89a5d9eaa646c846c9f464a0ab9c6ae262fdb19
--- /dev/null
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+ - repo: https://github.com/asottile/pyupgrade
+ rev: v3.3.1
+ hooks:
+ - id: pyupgrade
+ args: ['--keep-percent-format', '--py39-plus']
+ - repo: https://github.com/adamchainz/django-upgrade
+ rev: 1.10.0
+ hooks:
+ - id: django-upgrade
+ args: [--target-version, "3.2"]
+ - repo: https://github.com/psf/black
+ rev: 23.1.0
+ hooks:
+ - id: black
+ args: ['--target-version', 'py39', '--skip-string-normalization', '--line-length', '110']
+ - repo: https://github.com/PyCQA/isort
+ rev: 5.12.0
+ hooks:
+ - id: isort
+ args: ['--profile', 'black', '--line-length', '110']
+ - repo: https://github.com/rtts/djhtml
+ rev: '3.0.5'
+ hooks:
+ - id: djhtml
+ args: ['--tabwidth', '2']
include COPYING
include README
include MANIFEST.in
+include VERSION
recursive-include panikombo/static *.js
recursive-include panikombo/templates *.html
Section: python
Priority: optional
Maintainer: Frederic Peters <fred@radiopanik.org>
-Build-Depends: debhelper (>= 10),
+Build-Depends: debhelper-compat (= 12),
python3-all,
python3-django,
python3-setuptools,
--- /dev/null
+3.0 (quilt)
-import json
-
from django import forms
-from django_select2.forms import HeavySelect2Widget
+from django.forms.widgets import Widget
+from emissions.models import Episode, SoundFile
from taggit.forms import TagWidget
-from emissions.models import SoundFile, Episode
+from .models import EpisodeAutoSelectionCell, EpisodeCell, NewsItemAutoSelectionCell, SoundCell
+
+
+class BaseSelect2Widget(Widget):
+ template_name = "panikombo/select2.html"
-from .models import (SoundCell, EpisodeCell, EpisodeAutoSelectionCell,
- NewsItemAutoSelectionCell)
-from .views import soundfiles, episodes
+ def get_context(self, name, value, attrs):
+ context = super().get_context(name, value, attrs)
+ context['view_name'] = self.view_name
+ if value:
+ context['widget']['view_value'] = self.view_value(value)
+ return context
-class SoundFileWidget(HeavySelect2Widget):
- def render_texts(self, selected_choices, choices):
- queryset = SoundFile.objects.filter(id__in=selected_choices)
- def fmt(soundfile):
- return '%s - %s - %s' % (soundfile.episode.emission.title,
- soundfile.episode.title,
- soundfile.title or soundfile.id)
- texts = [fmt(soundfile) for soundfile in queryset.select_related()]
- return json.dumps(texts)
+
+class SoundFileWidget(BaseSelect2Widget):
+ view_name = 'panikombo-select2-soundfiles'
+
+ def view_value(self, value):
+ try:
+ soundfile = SoundFile.objects.get(id=value)
+ except SoundFile.DoesNotExist:
+ return 'missing sound %s' % value
+ return '%s - %s - %s' % (
+ soundfile.episode.emission.title,
+ soundfile.episode.title,
+ soundfile.title or soundfile.id,
+ )
class SoundCellForm(forms.ModelForm):
fields = ('soundfile',)
def __init__(self, *args, **kwargs):
- super(SoundCellForm, self).__init__(*args, **kwargs)
- self.fields['soundfile'].widget = SoundFileWidget(data_view=soundfiles)
+ super().__init__(*args, **kwargs)
+ self.fields['soundfile'].widget = SoundFileWidget()
+
+class EpisodeWidget(BaseSelect2Widget):
+ view_name = 'panikombo-select2-episodes'
-class EpisodeWidget(HeavySelect2Widget):
- def render_texts(self, selected_choices, choices):
- queryset = Episode.objects.filter(id__in=selected_choices)
- def fmt(episode):
- return '%s - %s' % (episode.emission.title, episode.title)
- texts = [fmt(episode) for episode in queryset.select_related()]
- return json.dumps(texts)
+ def view_value(self, value):
+ try:
+ episode = Episode.objects.get(id=value)
+ except Episode.DoesNotExist:
+ return 'missing episode %s' % value
+ return '%s - %s' % (episode.emission.title, episode.title)
class EpisodeCellForm(forms.ModelForm):
class Meta:
model = EpisodeCell
- fields = ('episode', )
+ fields = ('episode',)
def __init__(self, *args, **kwargs):
- super(EpisodeCellForm, self).__init__(*args, **kwargs)
- self.fields['episode'].widget = EpisodeWidget(data_view=episodes)
+ super().__init__(*args, **kwargs)
+ self.fields['episode'].widget = EpisodeWidget()
class EpisodeAutoSelectionCellForm(forms.ModelForm):
class NewsItemAutoSelectionCellForm(forms.ModelForm):
class Meta:
model = NewsItemAutoSelectionCell
- fields = ('title', 'tags', 'and_tags', 'category', 'future')
+ fields = ('tags', 'and_tags', 'category', 'future', 'count')
widgets = {'tags': TagWidget()}
+from combo.data.models import CellBase, Page
from django.core.management.base import BaseCommand, CommandError
+from emissions.models import Episode, NewsItem
-from emissions.models import NewsItem, Episode
-
-from combo.data.models import Page, CellBase
from panikombo.models import ItemTopik
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('auth', '0001_initial'),
('emissions', '0001_initial'),
migrations.CreateModel(
name='SoundCell',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('placeholder', models.CharField(max_length=20)),
('order', models.PositiveIntegerField()),
('slug', models.SlugField(verbose_name='Slug', blank=True)),
('public', models.BooleanField(default=True, verbose_name='Public')),
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
- ('page', models.ForeignKey(to='data.Page')),
- ('soundfile', models.ForeignKey(to='emissions.SoundFile', null=True)),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+ (
+ 'soundfile',
+ models.ForeignKey(to='emissions.SoundFile', null=True, on_delete=models.SET_NULL),
+ ),
],
options={
'verbose_name': 'Sound',
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('auth', '0001_initial'),
('emissions', '0003_newsitem_event_date'),
migrations.CreateModel(
name='EpisodeCell',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('placeholder', models.CharField(max_length=20)),
('order', models.PositiveIntegerField()),
('slug', models.SlugField(verbose_name='Slug', blank=True)),
('public', models.BooleanField(default=True, verbose_name='Public')),
- ('episode', models.ForeignKey(to='emissions.Episode', null=True)),
+ ('episode', models.ForeignKey(to='emissions.Episode', null=True, on_delete=models.SET_NULL)),
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
- ('page', models.ForeignKey(to='data.Page')),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
],
options={
'verbose_name': 'Episode',
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
import taggit.managers
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('auth', '0001_initial'),
('data', '0005_auto_20150226_0903'),
migrations.CreateModel(
name='EpisodeAutoSelectionCell',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('placeholder', models.CharField(max_length=20)),
('order', models.PositiveIntegerField()),
('slug', models.SlugField(verbose_name='Slug', blank=True)),
('public', models.BooleanField(default=True, verbose_name='Public')),
('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
- ('category', models.ForeignKey(blank=True, to='emissions.Category', null=True)),
+ (
+ 'category',
+ models.ForeignKey(
+ blank=True, to='emissions.Category', null=True, on_delete=models.SET_NULL
+ ),
+ ),
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
- ('page', models.ForeignKey(to='data.Page')),
- ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+ (
+ 'tags',
+ taggit.managers.TaggableManager(
+ to='taggit.Tag',
+ through='taggit.TaggedItem',
+ blank=True,
+ help_text='A comma-separated list of tags.',
+ verbose_name='Tags',
+ ),
+ ),
],
options={
'verbose_name': 'Automatic Episode Selection',
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
import taggit.managers
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('auth', '0001_initial'),
('data', '0005_auto_20150226_0903'),
migrations.CreateModel(
name='NewsItemAutoSelectionCell',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('placeholder', models.CharField(max_length=20)),
('order', models.PositiveIntegerField()),
('slug', models.SlugField(verbose_name='Slug', blank=True)),
('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
('future', models.BooleanField(default=True, verbose_name='Future Events Only')),
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
- ('page', models.ForeignKey(to='data.Page')),
- ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+ (
+ 'tags',
+ taggit.managers.TaggableManager(
+ to='taggit.Tag',
+ through='taggit.TaggedItem',
+ blank=True,
+ help_text='A comma-separated list of tags.',
+ verbose_name='Tags',
+ ),
+ ),
],
options={
'verbose_name': 'Automatic Newsitem Selection',
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('data', '0005_auto_20150226_0903'),
('panikombo', '0004_newsitemautoselectioncell'),
migrations.CreateModel(
name='Topik',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('image', models.ImageField(max_length=250, null=True, verbose_name='Image', blank=True)),
('got_focus', models.DateTimeField(default=None, null=True, blank=True)),
('has_focus', models.BooleanField(default=False)),
- ('page', models.ForeignKey(to='data.Page')),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.CASCADE)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('emissions', '0004_focus_page'),
('panikombo', '0005_topik'),
migrations.CreateModel(
name='ItemTopik',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('episode', models.ForeignKey(verbose_name='Episode', blank=True, to='emissions.Episode', null=True)),
- ('newsitem', models.ForeignKey(verbose_name='News Item', blank=True, to='emissions.NewsItem', null=True)),
- ('topik', models.ForeignKey(verbose_name=b'Topik', blank=True, to='panikombo.Topik', null=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
+ (
+ 'episode',
+ models.ForeignKey(
+ verbose_name='Episode',
+ blank=True,
+ to='emissions.Episode',
+ null=True,
+ on_delete=models.SET_NULL,
+ ),
+ ),
+ (
+ 'newsitem',
+ models.ForeignKey(
+ verbose_name='News Item',
+ blank=True,
+ to='emissions.NewsItem',
+ null=True,
+ on_delete=models.SET_NULL,
+ ),
+ ),
+ (
+ 'topik',
+ models.ForeignKey(
+ verbose_name=b'Topik',
+ blank=True,
+ to='panikombo.Topik',
+ null=True,
+ on_delete=models.SET_NULL,
+ ),
+ ),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('emissions', '0004_focus_page'),
('panikombo', '0006_itemtopik'),
migrations.AddField(
model_name='newsitemautoselectioncell',
name='category',
- field=models.ForeignKey(verbose_name='Category', blank=True, to='emissions.NewsCategory', null=True),
+ field=models.ForeignKey(
+ verbose_name='Category',
+ blank=True,
+ to='emissions.NewsCategory',
+ null=True,
+ on_delete=models.SET_NULL,
+ ),
preserve_default=True,
),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
import ckeditor.fields
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('auth', '0001_initial'),
('data', '0009_auto_20150529_2247'),
migrations.CreateModel(
name='TopikCell',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('placeholder', models.CharField(max_length=20)),
('order', models.PositiveIntegerField()),
('slug', models.SlugField(verbose_name='Slug', blank=True)),
('public', models.BooleanField(default=True, verbose_name='Public')),
('text', ckeditor.fields.RichTextField(null=True, verbose_name='Text', blank=True)),
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
- ('page', models.ForeignKey(to='data.Page')),
- ('topik', models.ForeignKey(to='panikombo.Topik', null=True)),
+ ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+ ('topik', models.ForeignKey(to='panikombo.Topik', null=True, on_delete=models.SET_NULL)),
],
options={
'verbose_name': 'Topik',
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0008_topikcell'),
]
migrations.AddField(
model_name='episodeautoselectioncell',
name='period',
- field=models.PositiveSmallIntegerField(default=0, verbose_name='Period', choices=[(0, 'All'), (1, 'Future'), (2, 'Past')]),
+ field=models.PositiveSmallIntegerField(
+ default=0, verbose_name='Period', choices=[(0, 'All'), (1, 'Future'), (2, 'Past')]
+ ),
preserve_default=True,
),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0009_episodeautoselectioncell_period'),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
+import datetime
from django.db import migrations, models
-import datetime
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0010_auto_20160220_1153'),
]
migrations.AddField(
model_name='episodeautoselectioncell',
name='last_update_timestamp',
- field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 35, 51768), auto_now=True),
+ field=models.DateTimeField(
+ default=datetime.datetime(2017, 4, 18, 11, 54, 35, 51768), auto_now=True
+ ),
preserve_default=False,
),
migrations.AddField(
migrations.AddField(
model_name='episodecell',
name='last_update_timestamp',
- field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 36, 700929), auto_now=True),
+ field=models.DateTimeField(
+ default=datetime.datetime(2017, 4, 18, 11, 54, 36, 700929), auto_now=True
+ ),
preserve_default=False,
),
migrations.AddField(
migrations.AddField(
model_name='newsitemautoselectioncell',
name='last_update_timestamp',
- field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 39, 362967), auto_now=True),
+ field=models.DateTimeField(
+ default=datetime.datetime(2017, 4, 18, 11, 54, 39, 362967), auto_now=True
+ ),
preserve_default=False,
),
migrations.AddField(
migrations.AddField(
model_name='soundcell',
name='last_update_timestamp',
- field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 42, 662255), auto_now=True),
+ field=models.DateTimeField(
+ default=datetime.datetime(2017, 4, 18, 11, 54, 42, 662255), auto_now=True
+ ),
preserve_default=False,
),
migrations.AddField(
migrations.AddField(
model_name='topikcell',
name='last_update_timestamp',
- field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 44, 42144), auto_now=True),
+ field=models.DateTimeField(
+ default=datetime.datetime(2017, 4, 18, 11, 54, 44, 42144), auto_now=True
+ ),
preserve_default=False,
),
]
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0011_auto_20170418_1154'),
]
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-06-11 11:21
-from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
('data', '0009_auto_20150529_2247'),
('panikombo', '0012_auto_20171015_1027'),
migrations.AddField(
model_name='itemtopik',
name='page',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+ field=models.ForeignKey(
+ blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='data.Page'
+ ),
),
migrations.AlterField(
model_name='itemtopik',
name='topik',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='panikombo.Topik', verbose_name='Topik'),
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to='panikombo.Topik',
+ verbose_name='Topik',
+ ),
),
]
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-06-11 11:26
-from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0013_auto_20200611_1121'),
]
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-06-11 12:50
-from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
('panikombo', '0014_remove_itemtopik_topik'),
]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-21 12:40
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('auth', '0008_alter_user_username_max_length'),
+ ('panikombo', '0015_auto_20200611_1250'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SoundsCell',
+ fields=[
+ (
+ 'id',
+ models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ ('placeholder', models.CharField(max_length=20)),
+ ('order', models.PositiveIntegerField()),
+ ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+ (
+ 'extra_css_class',
+ models.CharField(
+ blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+ ),
+ ),
+ ('public', models.BooleanField(default=True, verbose_name='Public')),
+ (
+ 'restricted_to_unlogged',
+ models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+ ),
+ ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+ (
+ 'include_search_input',
+ models.BooleanField(default=True, verbose_name='Include search input'),
+ ),
+ ('include_fragments', models.BooleanField(default=True, verbose_name='Include fragments')),
+ (
+ 'limit_to_focus',
+ models.BooleanField(default=False, verbose_name='Limit to focused elements'),
+ ),
+ ('count', models.PositiveSmallIntegerField(default=20, verbose_name='Count')),
+ ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
+ ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page')),
+ ],
+ options={
+ 'verbose_name': 'Sounds',
+ },
+ ),
+ ]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-21 14:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0016_soundscell'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='soundscell',
+ name='title',
+ field=models.CharField(blank=True, max_length=150, verbose_name='Title'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-21 20:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0017_soundscell_title'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='soundscell',
+ name='sort_order',
+ field=models.CharField(
+ choices=[
+ ('-creation_timestamp', 'Reverse chronological (creation)'),
+ ('-first_diffusion', 'Reverse chronological (diffusion)'),
+ ('creation_timestamp', 'Chronological (creation)'),
+ ('first_diffusion', 'Chronological (diffusion)'),
+ ('?', 'Random'),
+ ],
+ default='-creation_timestamp',
+ max_length=30,
+ verbose_name='Sort order',
+ ),
+ ),
+ ]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-22 14:02
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('emissions', '0015_auto_20200404_1510'),
+ ('panikombo', '0018_soundscell_sort_order'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='soundscell',
+ name='sound_format',
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to='emissions.Format',
+ verbose_name='Limit to format',
+ ),
+ ),
+ ]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-22 20:05
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0019_soundscell_sound_format'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='soundscell',
+ name='maximal_duration',
+ field=models.PositiveIntegerField(
+ blank=True, default=None, null=True, verbose_name='Maximal duration (in minutes)'
+ ),
+ ),
+ migrations.AddField(
+ model_name='soundscell',
+ name='minimal_duration',
+ field=models.PositiveIntegerField(
+ blank=True, default=None, null=True, verbose_name='Minimal duration (in minutes)'
+ ),
+ ),
+ ]
--- /dev/null
+# Generated by Django 1.11.29 on 2020-11-26 12:52
+
+import taggit.managers
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0020_auto_20201122_2005'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='soundscell',
+ name='tags',
+ field=taggit.managers.TaggableManager(
+ blank=True,
+ help_text='A comma-separated list of tags.',
+ through='taggit.TaggedItem',
+ to='taggit.Tag',
+ verbose_name='Tags',
+ ),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2.19 on 2021-03-26 13:24
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0021_soundscell_tags'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='episodeautoselectioncell',
+ name='category',
+ field=models.ForeignKey(
+ blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.Category'
+ ),
+ ),
+ migrations.AlterField(
+ model_name='episodeautoselectioncell',
+ name='page',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+ ),
+ migrations.AlterField(
+ model_name='episodecell',
+ name='episode',
+ field=models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.Episode'
+ ),
+ ),
+ migrations.AlterField(
+ model_name='episodecell',
+ name='page',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+ ),
+ migrations.AlterField(
+ model_name='itemtopik',
+ name='page',
+ field=models.ForeignKey(
+ blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='data.Page'
+ ),
+ ),
+ migrations.AlterField(
+ model_name='newsitemautoselectioncell',
+ name='page',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+ ),
+ migrations.AlterField(
+ model_name='soundcell',
+ name='page',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+ ),
+ migrations.AlterField(
+ model_name='soundcell',
+ name='soundfile',
+ field=models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.SoundFile'
+ ),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2.19 on 2021-08-18 09:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0022_auto_20210326_1324'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='episodecell',
+ name='template_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ migrations.AddField(
+ model_name='soundcell',
+ name='template_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ migrations.AddField(
+ model_name='soundscell',
+ name='template_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2.19 on 2021-08-18 11:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0023_auto_20210818_0906'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='episodeautoselectioncell',
+ name='template_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ migrations.AddField(
+ model_name='newsitemautoselectioncell',
+ name='template_name',
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2.28 on 2022-07-14 08:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0024_auto_20210818_1158'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='episodeautoselectioncell',
+ name='condition',
+ field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+ ),
+ migrations.AddField(
+ model_name='episodecell',
+ name='condition',
+ field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+ ),
+ migrations.AddField(
+ model_name='newsitemautoselectioncell',
+ name='condition',
+ field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+ ),
+ migrations.AddField(
+ model_name='soundcell',
+ name='condition',
+ field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+ ),
+ migrations.AddField(
+ model_name='soundscell',
+ name='condition',
+ field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-07-25 17:11
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('data', '0065_snapshot_uuids'),
+ ('auth', '0008_alter_user_username_max_length'),
+ ('panikombo', '0025_auto_20220714_0830'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='episodeautoselectioncell',
+ name='groups',
+ field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+ ),
+ migrations.AlterField(
+ model_name='episodecell',
+ name='groups',
+ field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+ ),
+ migrations.AlterField(
+ model_name='newsitemautoselectioncell',
+ name='groups',
+ field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+ ),
+ migrations.AlterField(
+ model_name='soundcell',
+ name='groups',
+ field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+ ),
+ migrations.AlterField(
+ model_name='soundscell',
+ name='groups',
+ field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-07-25 17:13
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('auth', '0008_alter_user_username_max_length'),
+ ('data', '0065_snapshot_uuids'),
+ ('panikombo', '0026_auto_20230725_1711'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='WeekProgramCell',
+ fields=[
+ (
+ 'id',
+ models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ ('placeholder', models.CharField(max_length=20)),
+ ('order', models.PositiveIntegerField()),
+ ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+ (
+ 'extra_css_class',
+ models.CharField(
+ blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+ ),
+ ),
+ (
+ 'template_name',
+ models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ (
+ 'condition',
+ models.CharField(
+ blank=True, max_length=1000, null=True, verbose_name='Display condition'
+ ),
+ ),
+ ('public', models.BooleanField(default=True, verbose_name='Public')),
+ (
+ 'restricted_to_unlogged',
+ models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+ ),
+ ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+ ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+ ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+ ],
+ options={
+ 'abstract': False,
+ 'verbose_name': 'Week Program',
+ },
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-07-25 17:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0027_weekprogramcell'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='weekprogramcell',
+ name='include_nonstop',
+ field=models.BooleanField(default=True, verbose_name='Include nonstop'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-07-25 18:24
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('auth', '0008_alter_user_username_max_length'),
+ ('data', '0065_snapshot_uuids'),
+ ('panikombo', '0028_weekprogramcell_include_nonstop'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='FocusCarrouselCell',
+ fields=[
+ (
+ 'id',
+ models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ ('placeholder', models.CharField(max_length=20)),
+ ('order', models.PositiveIntegerField()),
+ ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+ (
+ 'extra_css_class',
+ models.CharField(
+ blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+ ),
+ ),
+ (
+ 'template_name',
+ models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ (
+ 'condition',
+ models.CharField(
+ blank=True, max_length=1000, null=True, verbose_name='Display condition'
+ ),
+ ),
+ ('public', models.BooleanField(default=True, verbose_name='Public')),
+ (
+ 'restricted_to_unlogged',
+ models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+ ),
+ ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+ ('count', models.PositiveSmallIntegerField(default=3, verbose_name='Count')),
+ ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+ ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+ ],
+ options={
+ 'verbose_name': 'Focus carrousel',
+ },
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-07-25 20:23
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('auth', '0008_alter_user_username_max_length'),
+ ('data', '0065_snapshot_uuids'),
+ ('panikombo', '0029_focuscarrouselcell'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='EmissionsCell',
+ fields=[
+ (
+ 'id',
+ models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+ ),
+ ('placeholder', models.CharField(max_length=20)),
+ ('order', models.PositiveIntegerField()),
+ ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+ (
+ 'extra_css_class',
+ models.CharField(
+ blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+ ),
+ ),
+ (
+ 'template_name',
+ models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+ ),
+ (
+ 'condition',
+ models.CharField(
+ blank=True, max_length=1000, null=True, verbose_name='Display condition'
+ ),
+ ),
+ ('public', models.BooleanField(default=True, verbose_name='Public')),
+ (
+ 'restricted_to_unlogged',
+ models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+ ),
+ ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+ ('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
+ ('count', models.PositiveSmallIntegerField(default=3, verbose_name='Count')),
+ ('include_active', models.BooleanField(default=True, verbose_name='Include active')),
+ ('include_archived', models.BooleanField(default=False, verbose_name='Include archived')),
+ (
+ 'sort_order',
+ models.CharField(
+ choices=[
+ ('title', 'Alphabetical'),
+ ('-creation_timestamp', 'Reverse chronological (latest emissions)'),
+ ('?', 'Random'),
+ ],
+ default='-creation_timestamp',
+ max_length=30,
+ verbose_name='Sort order',
+ ),
+ ),
+ ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+ ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+ ],
+ options={
+ 'verbose_name': 'Emissions',
+ },
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.19 on 2023-09-02 18:01
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('panikombo', '0030_emissionscell'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='episodeautoselectioncell',
+ options={'verbose_name': 'Episodes'},
+ ),
+ migrations.AlterModelOptions(
+ name='newsitemautoselectioncell',
+ options={'verbose_name': 'Newsitems'},
+ ),
+ migrations.AddField(
+ model_name='newsitemautoselectioncell',
+ name='count',
+ field=models.PositiveSmallIntegerField(default=20, verbose_name='Count'),
+ ),
+ ]
-# coding: utf-8
import collections
-COMBO_PUBLIC_TEMPLATES = collections.OrderedDict({
- 'standard': {
- 'name': 'Page normale',
- 'template': 'combo/page_template_sidebar.html',
- 'placeholders': collections.OrderedDict({
- 'content': {
- 'name': 'Contenu',
+COMBO_PUBLIC_TEMPLATES = collections.OrderedDict(
+ {
+ 'standard': {
+ 'name': 'Page avec barre latérale',
+ 'template': 'combo/page_template_sidebar.html',
+ 'placeholders': collections.OrderedDict(
+ {
+ 'introduction': {
+ 'name': 'Introduction',
+ 'optional': True,
+ },
+ 'content': {
+ 'name': 'Contenu',
+ },
+ 'sidebar': {
+ 'name': 'Barre latérale',
+ },
+ }
+ ),
+ },
+ 'fullwidth': {
+ 'name': 'Page prenant toute la largeur',
+ 'template': 'combo/page_template_full_width.html',
+ 'placeholders': {
+ 'introduction': {
+ 'name': 'Introduction',
+ 'optional': True,
+ },
+ 'content': {
+ 'name': 'Contenu',
+ },
},
- 'sidebar': {
- 'name': 'Barre latérale',
+ },
+ 'standard-about': {
+ 'name': 'Section « À propos »',
+ 'template': 'combo/page_template_about.html',
+ 'placeholders': {
+ 'content': {
+ 'name': 'Contenu',
+ },
},
- })
- },
- 'fullwidth': {
- 'name': 'Page prenant toute la largeur',
- 'template': 'combo/page_template_full_width.html',
- 'placeholders': {
- 'content': {
- 'name': 'Contenu',
- },
- }
- },
- 'standard-about': {
- 'name': 'Section « À propos »',
- 'template': 'combo/page_template_about.html',
- 'placeholders': {
- 'content': {
- 'name': 'Contenu',
- },
- }
- },
-})
+ },
+ }
+)
+
+COMBO_CELL_TEMPLATES = {
+ 'data_menucell': {
+ 'horizontal': {
+ 'label': 'Horizontal',
+ 'extra-css-classes': 'menu-horizontal',
+ },
+ 'vertical': {
+ 'label': 'Vertical',
+ 'extra-css-classes': 'menu-vertical',
+ },
+ 'topiks': {
+ 'label': 'Topiks',
+ 'template': 'cells/menu-topiks.html',
+ },
+ }
+}
-from datetime import date
-import os
+from datetime import date, datetime, timedelta
+from combo.data.library import register_cell_class
+from combo.data.models import CellBase
from django import template
from django.db import models
-from django.db.models.functions import Lower
-from django.utils.encoding import force_text, python_2_unicode_compatible
-from django.utils.translation import ugettext_lazy as _
-
-from ckeditor.fields import RichTextField
-from taggit.models import Tag
+from django.utils.translation import gettext_lazy as _
+from emissions.models import Emission, Episode, Focus, NewsItem, SoundFile
+from emissions.utils import period_program
from taggit.managers import TaggableManager
+from taggit.models import Tag
from taggit.utils import parse_tags
-from combo.data.models import CellBase
-from combo.data.library import register_cell_class
-
-from emissions.models import Episode, NewsItem
@register_cell_class
class SoundCell(CellBase):
- soundfile = models.ForeignKey('emissions.SoundFile', null=True)
+ soundfile = models.ForeignKey('emissions.SoundFile', null=True, on_delete=models.CASCADE)
class Meta:
verbose_name = _('Sound')
def get_default_form_class(self):
from .forms import SoundCellForm
+
return SoundCellForm
def get_included_items(self):
def get_additional_label(self):
if self.soundfile:
if self.soundfile.fragment:
- return u'%s - %s - %s' % (
- self.soundfile.episode.emission.title,
- self.soundfile.episode.title,
- self.soundfile.title)
+ return '%s - %s - %s' % (
+ self.soundfile.episode.emission.title,
+ self.soundfile.episode.title,
+ self.soundfile.title,
+ )
else:
- return u'%s - %s' % (
- self.soundfile.episode.emission.title,
- self.soundfile.episode.title)
+ return '%s - %s' % (self.soundfile.episode.emission.title, self.soundfile.episode.title)
return ''
@register_cell_class
class EpisodeCell(CellBase):
- episode = models.ForeignKey('emissions.Episode', null=True)
+ episode = models.ForeignKey('emissions.Episode', null=True, on_delete=models.CASCADE)
class Meta:
verbose_name = _('Episode')
def get_default_form_class(self):
from .forms import EpisodeCellForm
+
return EpisodeCellForm
def get_additional_label(self):
if self.episode:
- return u'%s - %s' % (
- self.episode.emission.title,
- self.episode.title)
+ return '%s - %s' % (self.episode.emission.title, self.episode.title)
return ''
title = models.CharField(_('Title'), max_length=50, blank=True)
tags = TaggableManager(_('Tags'), blank=True)
and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
- category = models.ForeignKey('emissions.Category', null=True, blank=True)
+ category = models.ForeignKey('emissions.Category', null=True, blank=True, on_delete=models.CASCADE)
period = models.PositiveSmallIntegerField(
- _('Period'), default=0,
- choices=((0, _('All')),
- (1, _('Future')),
- (2, _('Past'))))
-
- template_name = 'panikombo/episode_auto_selection.html'
+ _('Period'), default=0, choices=((0, _('All')), (1, _('Future')), (2, _('Past')))
+ )
+ default_template_name = 'panikombo/episode_auto_selection.html'
class Meta:
- verbose_name = _('Automatic Episode Selection')
+ verbose_name = _('Episodes')
def get_included_items(self):
episodes_queryset = Episode.objects.select_related()
if self.period == 0:
episodes_queryset = episodes_queryset.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'])
+ 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'],
+ )
episodes_queryset = episodes_queryset.order_by('first_diffusion').distinct()
elif self.period == 1:
episodes_queryset = episodes_queryset.extra(
- select={ 'first_diffusion': 'emissions_diffusion.datetime', },
- select_params=(False, True),
- where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
+ select={
+ 'first_diffusion': 'emissions_diffusion.datetime',
+ },
+ select_params=(False, True),
+ where=[
+ '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
WHERE episode_id = emissions_episode.id) AND
- datetime >= CURRENT_TIMESTAMP'''],
- tables=['emissions_diffusion'])
+ datetime >= CURRENT_TIMESTAMP'''
+ ],
+ tables=['emissions_diffusion'],
+ )
episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
elif self.period == 2:
episodes_queryset = episodes_queryset.extra(
- select={ 'first_diffusion': 'emissions_diffusion.datetime', },
- select_params=(False, True),
- where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
+ select={
+ 'first_diffusion': 'emissions_diffusion.datetime',
+ },
+ select_params=(False, True),
+ where=[
+ '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
WHERE episode_id = emissions_episode.id) AND
- datetime < CURRENT_TIMESTAMP'''],
- tables=['emissions_diffusion'])
+ datetime < CURRENT_TIMESTAMP'''
+ ],
+ tables=['emissions_diffusion'],
+ )
episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
return episodes_queryset
def get_cell_extra_context(self, context):
- ctx = super(EpisodeAutoSelectionCell, self).get_cell_extra_context(context)
+ ctx = super().get_cell_extra_context(context)
ctx['title'] = self.title
- if (self.category or self.period or self.tags.count()):
+ if self.category or self.period or self.tags.count():
ctx['episodes'] = self.get_included_items()
else:
ctx['episodes'] = []
def get_default_form_class(self):
from .forms import EpisodeAutoSelectionCellForm
+
return EpisodeAutoSelectionCellForm
def get_additional_label(self):
return self.title
return ''
+
@register_cell_class
class NewsItemAutoSelectionCell(CellBase):
title = models.CharField(_('Title'), max_length=50, blank=True)
tags = TaggableManager(_('Tags'), blank=True)
and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
future = models.BooleanField(_('Future Events Only'), default=True)
- category = models.ForeignKey('emissions.NewsCategory',
- verbose_name=_('Category'), null=True, blank=True)
+ category = models.ForeignKey(
+ 'emissions.NewsCategory', verbose_name=_('Category'), null=True, blank=True, on_delete=models.SET_NULL
+ )
+ count = models.PositiveSmallIntegerField(_('Count'), default=20)
- template_name = 'panikombo/newsitem_auto_selection.html'
+ default_template_name = 'panikombo/newsitem_auto_selection.html'
class Meta:
- verbose_name = _('Automatic Newsitem Selection')
+ verbose_name = _('Newsitems')
def get_included_items(self):
newsitems_queryset = NewsItem.objects.select_related()
if self.category:
newsitems_queryset = newsitems_queryset.filter(category=self.category)
newsitems_queryset = newsitems_queryset.order_by('-event_date', '-creation_timestamp')
- return newsitems_queryset
+ return newsitems_queryset[: self.count]
def get_cell_extra_context(self, context):
- ctx = super(NewsItemAutoSelectionCell, self).get_cell_extra_context(context)
+ ctx = super().get_cell_extra_context(context)
ctx['title'] = self.title
-
- if self.tags.count() or self.future or self.category:
- ctx['newsitems'] = self.get_included_items()
- else:
- ctx['newsitems'] = []
-
+ ctx['newsitems'] = self.get_included_items()
return ctx
def get_default_form_class(self):
from .forms import NewsItemAutoSelectionCellForm
+
return NewsItemAutoSelectionCellForm
def get_additional_label(self):
class ItemTopik(models.Model):
- newsitem = models.ForeignKey('emissions.NewsItem', verbose_name=_('News Item'),
- null=True, blank=True)
- episode = models.ForeignKey('emissions.Episode', verbose_name=_('Episode'),
- null=True, blank=True)
- page = models.ForeignKey('data.Page', null=True, blank=True)
+ newsitem = models.ForeignKey(
+ 'emissions.NewsItem', verbose_name=_('News Item'), null=True, blank=True, on_delete=models.SET_NULL
+ )
+ episode = models.ForeignKey(
+ 'emissions.Episode', verbose_name=_('Episode'), null=True, blank=True, on_delete=models.SET_NULL
+ )
+ page = models.ForeignKey('data.Page', null=True, blank=True, on_delete=models.SET_NULL)
+
+
+@register_cell_class
+class SoundsCell(CellBase):
+ title = models.CharField(_('Title'), max_length=150, blank=True)
+ include_search_input = models.BooleanField(_('Include search input'), default=True)
+ include_fragments = models.BooleanField(_('Include fragments'), default=True)
+ limit_to_focus = models.BooleanField(_('Limit to focused elements'), default=False)
+ sound_format = models.ForeignKey(
+ 'emissions.Format', verbose_name=_('Limit to format'), null=True, blank=True, on_delete=models.CASCADE
+ )
+ tags = TaggableManager(_('Tags'), blank=True)
+ minimal_duration = models.PositiveIntegerField(
+ _('Minimal duration (in minutes)'), default=None, blank=True, null=True
+ )
+ maximal_duration = models.PositiveIntegerField(
+ _('Maximal duration (in minutes)'), default=None, blank=True, null=True
+ )
+ count = models.PositiveSmallIntegerField(_('Count'), default=20)
+ sort_order = models.CharField(
+ _('Sort order'),
+ default='-creation_timestamp',
+ max_length=30,
+ choices=[
+ ('-creation_timestamp', _('Reverse chronological (creation)')),
+ ('-first_diffusion', _('Reverse chronological (diffusion)')),
+ ('creation_timestamp', _('Chronological (creation)')),
+ ('first_diffusion', _('Chronological (diffusion)')),
+ ('?', _('Random')),
+ ],
+ )
+
+ class Meta:
+ verbose_name = _('Sounds')
+
+ def get_default_form_fields(self):
+ fields = super().get_default_form_fields()
+ fields.insert(fields.index('minimal_duration'), 'tags')
+ return fields
+
+ def get_cell_extra_context(self, context):
+ soundfiles = SoundFile.objects.prefetch_related('episode__emission__categories')
+ soundfiles = soundfiles.filter(podcastable=True)
+ soundfiles = soundfiles.exclude(creation_timestamp__isnull=True)
+ if not self.include_fragments:
+ soundfiles = soundfiles.filter(fragment=False)
+ if self.limit_to_focus:
+ soundfiles = soundfiles.filter(got_focus__isnull=False)
+ if self.sound_format:
+ soundfiles = soundfiles.filter(format_id=self.sound_format_id)
+ if self.minimal_duration:
+ soundfiles = soundfiles.filter(duration__gte=self.minimal_duration * 60)
+ if self.maximal_duration:
+ soundfiles = soundfiles.filter(duration__lte=self.maximal_duration * 60)
+ if self.tags.exists():
+ soundfiles = soundfiles.filter(episode__tags__in=self.tags.all())
+ soundfiles = (
+ soundfiles.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(self.sort_order)
+ .distinct()
+ )
+ return {
+ 'include_search_input': self.include_search_input,
+ 'soundfiles': soundfiles[: self.count],
+ }
+
+
+@register_cell_class
+class WeekProgramCell(CellBase):
+ include_nonstop = models.BooleanField(_('Include nonstop'), default=True)
+
+ default_template_name = 'panikombo/week_program.html'
+
+ class Meta:
+ verbose_name = _('Week Program')
+
+ @staticmethod
+ def tofirstdayinisoweek(year, week):
+ # from http://stackoverflow.com/questions/5882405/get-date-from-iso-week-number-in-python
+ ret = datetime.strptime('%04d-%02d-1' % (year, week), '%Y-%W-%w')
+ if datetime(year, 1, 4).isoweekday() > 4:
+ ret -= timedelta(days=7)
+ return ret
+
+ def get_cell_extra_context(self, context):
+ ctx = super().get_cell_extra_context(context)
+ year = context['request'].GET.get('year') if 'request' in context else None
+ week = context['request'].GET.get('week') if 'request' in context else None
+ weekday = context['request'].GET.get('weekday') if 'request' in context else None
+ year = int(year if year else datetime.today().isocalendar()[0])
+ week = int(week if week else datetime.today().isocalendar()[1])
+ weekday = int(weekday if weekday is not None else datetime.today().weekday())
+
+ date = WeekProgramCell.tofirstdayinisoweek(year, week)
+ date = datetime(*date.timetuple()[:3])
+
+ previous_week = date - timedelta(days=7)
+ previous_week_year, previous_week_no = previous_week.isocalendar()[:2]
+
+ next_week = date + timedelta(days=7)
+ next_week_year, next_week_no = next_week.isocalendar()[:2]
+
+ program = period_program(date, date + timedelta(days=7), include_nonstop=self.include_nonstop)
+ days = []
+ for day in range(7):
+ days.append(
+ {
+ 'cells': [x for x in program if x.is_on_weekday(day + 1)],
+ 'datetime': date + timedelta(days=day),
+ }
+ )
+
+ ctx.update(
+ {
+ 'days': days,
+ 'weekday': weekday,
+ 'week': week,
+ 'year': year,
+ 'previous_week_year': previous_week_year,
+ 'previous_week_no': previous_week_no,
+ 'next_week_year': next_week_year,
+ 'next_week_no': next_week_no,
+ }
+ )
+
+ return ctx
+
+
+@register_cell_class
+class FocusCarrouselCell(CellBase):
+ count = models.PositiveSmallIntegerField(_('Count'), default=3)
+
+ default_template_name = 'panikombo/focus_carrousel.html'
+
+ class Meta:
+ verbose_name = _('Focus carrousel')
+
+ def get_cell_extra_context(self, context):
+ ctx = super().get_cell_extra_context(context)
+ ctx['news'] = (
+ Focus.objects.filter(current=True)
+ .select_related('emission', 'newsitem', 'soundfile', 'episode', 'newsitem__category')
+ .order_by('?')[: self.count]
+ )
+ return ctx
+
+
+@register_cell_class
+class EmissionsCell(CellBase):
+ title = models.CharField(_('Title'), max_length=50, blank=True)
+ count = models.PositiveSmallIntegerField(_('Count'), default=3)
+ include_active = models.BooleanField(_('Include active'), default=True)
+ include_archived = models.BooleanField(_('Include archived'), default=False)
+ sort_order = models.CharField(
+ _('Sort order'),
+ default='-creation_timestamp',
+ max_length=30,
+ choices=[
+ ('title', _('Alphabetical')),
+ ('-creation_timestamp', _('Reverse chronological (latest emissions)')),
+ ('?', _('Random')),
+ ],
+ )
+
+ default_template_name = 'panikombo/emissions.html'
+
+ class Meta:
+ verbose_name = _('Emissions')
+
+ def get_cell_extra_context(self, context):
+ ctx = super().get_cell_extra_context(context)
+
+ qs = Emission.objects.all()
+ if not self.include_active:
+ qs = qs.exclude(archived=False)
+ if not self.include_archived:
+ qs = qs.exclude(archived=True)
+
+ qs = qs.order_by(self.sort_order)
+
+ ctx['emissions'] = qs[: self.count]
+
+ return ctx
--- /dev/null
+{% load paniktags thumbnail static %}
+{% if soundfile %}
+ <div class="wrapper extra-soundfiles">
+ <div class="logo">
+ {% if soundfile.episode.image %}
+ {% thumbnail soundfile.episode.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% elif soundfile.episode.emission.image %}
+ {% thumbnail soundfile.episode.emission.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% else %}
+ <img alt="" class="smooth" style="width:60px;" src="{% static "img/emission.png" %}"/>
+ {% endif %}
+ </div>
+ <ul class="padded custom list">
+ <li>
+ <div class="soundfile-info"><strong>
+ <a href="{% url 'emission-view' slug=soundfile.episode.emission.slug%}">{{ soundfile.episode.emission.title }}</a> -
+ <a href="{% url 'episode-view' emission_slug=soundfile.episode.emission.slug slug=soundfile.episode.slug %}">{{ soundfile.episode.title }}</a></strong>
+ {% if soundfile.fragment %}<span> - {{ soundfile.title }}</span>{% endif %}
+ </div>
+ {% audio sound=soundfile %}</li>
+ </ul>
+ </div>
+{% endif %}
--- /dev/null
+{% load i18n paniktags %}
+{% if cell.title %}
+ <h2 class="cell--title text-cell--title">{{ cell.title }}</h2>
+{% endif %}
+<ul class="custom list padded">
+ {% for emission in emissions %}
+ <li class="item">
+ {% emission_resume %}
+ </li>
+ {% endfor %}
+</ul>
--- /dev/null
+{% load paniktags thumbnail static %}
+{% if episode %}
+ <div class="wrapper extra-soundfiles">
+ <div class="logo">
+ {% if episode.image %}
+ {% thumbnail episode.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% elif episode.emission.image %}
+ {% thumbnail episode.emission.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% else %}
+ <img alt="" class="smooth" style="width:60px;" src="{% static "img/emission.png" %}"/>
+ {% endif %}
+ </div>
+ <ul class="padded custom list">
+ <li>
+ <div class="soundfile-info"><strong>
+ <a href="{% url 'emission-view' slug=episode.emission.slug%}">{{ episode.emission.title }}</a> -
+ <a href="{% url 'episode-view' emission_slug=episode.emission.slug slug=episode.slug %}">{{ episode.title }}</a></strong>
+ {% if soundfile.fragment %}<span> - {{ soundfile.title }}</span>{% endif %}
+ </div>
+ {% for diffusion in episode.diffusions %}
+ <span class="date">→ {{ diffusion.datetime|date:"l d M Y à H:i" }}</span>
+ {% endfor %}
+ {% if soundfile %}{% audio sound=soundfile %}{% endif %}
+ </li>
+ </ul>
+ </div>
+{% endif %}
--- /dev/null
+{% load paniktags thumbnail static %}
+{% if title and episodes %}<h3>{{title}}</h3>{% endif %}
+{% for episode in episodes %}
+
+ <div class="wrapper extra-soundfiles soundcell">
+ <div class="logo">
+ {% if episode.image %}
+ {% thumbnail episode.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% elif episode.emission.image %}
+ {% thumbnail episode.emission.image "60x60" crop="50% 25%" as im %}
+ <img alt="" width="60" height="60" src="{{im.url}}"/>
+ {% endthumbnail %}
+ {% else %}
+ <img alt="" class="smooth" style="width:60px;" src="{% static "img/emission.png" %}"/>
+ {% endif %}
+ </div>
+ <ul class="padded custom list">
+ <li>
+ <div class="soundfile-info"><strong>
+ <a class="emission-title" href="{% url 'emission-view' slug=episode.emission.slug%}">{{ episode.emission.title }}</a>
+ <span class="sep">-</span>
+ <a class="episode-title" href="{% url 'episode-view' emission_slug=episode.emission.slug slug=episode.slug %}">{{ episode.title }}</a></strong>
+ </div>
+ {% for diffusion in episode.diffusions %}
+ <span class="date">→ {{ diffusion.datetime|date:"l d M Y à H:i" }}</span>
+ {% endfor %}
+ {% if episode.main_sound %}{% audio sound=episode.main_sound %}{% endif %}
+ {% for sound in episode.fragment_sounds %}
+ <div class="fragment-sound">
+ {% audio sound=sound display_fragment_name=True %}
+ </div>
+ {% endfor %}
+ </li>
+ </ul>
+ </div>
+
+{% endfor %}
--- /dev/null
+{{form.as_p}}
--- /dev/null
+{% load thumbnail i18n paniktags %}
+<div id="newsRoll">
+ <div class="newsRoll">
+ <ul id="ticker" class="custom bigNews marged" style="height:300px;overflow:hidden;">
+ {% for focus in news %}
+ <li
+ id="newsRollId-{{ focus.id }}"
+ class="">
+ <a
+ {% thumbnail focus.content_image "500x375" crop="50% 25%" as im %}
+ style="max-width:100%;height:300px;background: no-repeat 50% 50% url('{{im.url}}');"
+ {% endthumbnail %}
+ class="block news relative"
+ href="{{ focus|get_focus_url }}">
+ {% if focus.content_category_title %}
+ <div class="labels">
+ <span>{{ focus.content_category_title }}</span>
+ </div>
+ {% endif %}
+
+ <div class="title"><div>{{ focus.focus_title }}</div></div>
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ <div class="marged">
+ <ul class="custom padded" id="roller">
+ {% for focus in news %}
+ <li class="num-{{ forloop.counter }} padded">
+ <button data-about="newsRollId-{{ focus.id }}">
+ {% thumbnail focus.content_image "160x120" crop="50% 25%" as im %}
+ <img loading="lazy" alt="{{ focus.focus_title }}" style="width:95%;" src="{{im.url}}" />
+ {% endthumbnail %}
+ </button>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+</div>
--- /dev/null
+{% load paniktags %}
+{% if title and newsitems %}<h3>{{title}}</h3>{% endif %}
+<ul class="custom list newsList">
+ {% for content in newsitems %}
+ <li>{% news_inline %}</li>
+ {% endfor %}
+</ul>
--- /dev/null
+<select style="width: 100%" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %}>
+ {% if widget.value != None %}<option value="{{ widget.value }}">{{widget.view_value}}</option>{% endif %}
+</select>
+<script>
+ $(function() {
+ var options = {
+ placeholder: '',
+ minimumInputLength: 3,
+ ajax: {
+ url: function() {
+ return "{% url view_name %}";
+ },
+ dataType: 'json',
+ data: function(params) {
+ var query = {
+ term: params.term,
+ }
+ return query;
+ },
+ },
+ };
+ $('select[name={{widget.name}}]').select2(options);
+ })
+</script>
--- /dev/null
+{% load i18n paniktags static %}
+
+{% block program-header %}
+ <div class="program tabs" data-tab-about="#weekProgramContent-{{ week|slugify }}">
+ <nav class="">
+ <ul class="days custom distributed">
+ <li class="week-arrow week-arrow-prev"><button data-year="{{previous_week_year}}" data-week="{{previous_week_no}}"
+ class="icon-chevron-sign-left"><span class="sr-only">{% trans "Previous Week" %}</span></button></li>
+ {% for day in days %}
+ <li class="weektab-{{forloop.counter}}"><button class="{% if day.datetime.weekday == weekday %}active{% endif %}" data-tab="#Program-week-{{ day.datetime|slugify }}" data-neau-text="{{ day.datetime|date:"d.m.y"}}"><span class="day-label">{{ day.datetime|date:"D" }}</span> <span class="date-label">{{ day.datetime|date:"d/m" }}</span></button></li>
+ {% endfor %}
+ <li class="week-arrow week-arrow-next"><button data-year="{{next_week_year}}" data-week="{{next_week_no}}"
+ class="icon-chevron-sign-right" ><span class="sr-only">{% trans "Next Week" %}</span></button></li>
+ </ul>
+ </nav>
+ </div>
+{% endblock %}
+
+{% block program-content %}
+ <div id="weekProgramContent-{{ week|slugify }}" class="program {% if current_week %}current-week{% endif %}">
+
+ {% for day in days %}
+ <div data-tabbed="true" class="content" id="Program-week-{{ day.datetime|slugify }}"
+ {% if day.datetime.weekday != weekday %}style="display: none"{% endif %}
+ >
+ <ul class="custom program-week list">
+ {% for cell in day.cells %}
+ <li class="cf {% if cell.end_datetime < now %}past{% elif cell.datetime >= now %}future{% else %}current{% endif %}"
+ data-program-slug="{% firstof cell.emission.slug cell.episode.emission.slug cell.slug %}">
+ {% block week-program-line %}
+ <div class="programDate"><strong>{{ cell.datetime|date:"H:i" }}</strong></div>
+ <div class="programCell">
+ {% if cell.episode %}
+ {% with cell.episode as episode %}{% episode_resume model="inline" klass="standalone" date=False %}{% endwith %}
+ {% elif cell.emission %}
+ {% with cell.emission as emission %}{% emission_resume %}{% endwith %}
+ {% else %}
+ <a href="{% if cell.nonstop.redirect_path %}{{ cell.nonstop.redirect_path }}{% else %}{% url 'emission-view' slug=cell.slug %}{% endif %}" class="nonstop"><em>{{ cell.label }}</em></a> - <span class="smooth categories category">Musique en continu</span> - <a class="playlist" href="{% url 'nonstop-playlist' slug=cell.slug year=cell.datetime.year month=cell.datetime.month day=cell.datetime.day %}">playlist</a>
+ {% endif %}
+ </div>
+ {% endblock %}
+ </li>
+ {% empty %}
+ <li>{% block week-program-empty %}<div class="info big">Non stop only!</div>{% endblock %}</li>
+ {% endfor %}
+ </ul>
+ </div>
+ {% endfor %}
+ </div>
+{% endblock %}
+
+{% block scripts %}
+ <script src="{% static "js/combo.public.js" %}"></script>
+ <script>
+ $(function() {
+ $('button[data-year][data-week]').on('click', function(e) {
+ var $cell = $(this).parents('[data-ajax-cell-url]');
+ $cell.data('extra-context',
+ $cell.data('extra-context') + '&year=' + $(this).data('year') + '&week=' + $(this).data('week'));
+ combo_load_cell($cell);
+ e.preventDefault();
+ return false;
+ });
+ if (! window.week_program_initialized) {
+ $(document).on('combo:cell-loaded', function(ev, cell) {
+ if ($(cell).is('.week-program-cell')) {
+ window.panikweb_init_page();
+ }
+ });
+ window.week_program_initialized = true;
+ }
+ });
+ </script>
+{% endblock %}
--- /dev/null
+from django.urls import path
+
+from . import views
+
+urlpatterns = [
+ path('select2/episodes/', views.episodes, name='panikombo-select2-episodes'),
+ path('select2/soundfiles/', views.soundfiles, name='panikombo-select2-soundfiles'),
+]
-from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
from django.db.models import Q
-from django.http import Http404, JsonResponse
-from django.views.generic.edit import UpdateView
-import django_select2.views
-
-from emissions.models import SoundFile, Episode
-
-
-class SoundFilesView(django_select2.views.AutoResponseView):
- def get(self, request, *args, **kwargs):
- terms = kwargs.get('term', request.GET.get('term', ''))
- queryset = SoundFile.objects.all()
- for term in terms.split():
- queryset = queryset.filter(podcastable=True).filter(Q(title__icontains=term) |
- Q(episode__title__icontains=term) |
- Q(episode__emission__title__icontains=term))
- def fmt(soundfile):
- return '%s - %s - %s' % (soundfile.episode.emission.title,
- soundfile.episode.title,
- soundfile.title or soundfile.id)
-
- return JsonResponse({
+from django.http import JsonResponse
+from emissions.models import Episode, SoundFile
+
+
+@login_required
+def soundfiles(request, *args, **kwargs):
+ terms = kwargs.get('term', request.GET.get('term', ''))
+ queryset = SoundFile.objects.all()
+ for term in terms.split():
+ queryset = queryset.filter(podcastable=True).filter(
+ Q(title__icontains=term)
+ | Q(episode__title__icontains=term)
+ | Q(episode__emission__title__icontains=term)
+ )
+
+ def fmt(soundfile):
+ return '%s - %s - %s' % (
+ soundfile.episode.emission.title,
+ soundfile.episode.title,
+ soundfile.title or soundfile.id,
+ )
+
+ return JsonResponse(
+ {
'results': [
{
'text': fmt(x),
'id': x.pk,
}
for x in queryset
- ],
- 'more': False
- })
+ ],
+ 'more': False,
+ }
+ )
-soundfiles = SoundFilesView.as_view()
+@login_required
+def episodes(request, *args, **kwargs):
+ terms = kwargs.get('term', request.GET.get('term', ''))
+ queryset = Episode.objects.all()
+ for term in terms.split():
+ queryset = queryset.filter(Q(title__icontains=term) | Q(emission__title__icontains=term))
+ def fmt(episode):
+ return '%s - %s' % (episode.emission.title, episode.title)
-class EpisodesView(django_select2.views.AutoResponseView):
- def get(self, request, *args, **kwargs):
- terms = kwargs.get('term', request.GET.get('term', ''))
- queryset = Episode.objects.all()
- for term in terms.split():
- queryset = queryset.filter(Q(title__icontains=term) |
- Q(emission__title__icontains=term))
- def fmt(episode):
- return '%s - %s' % (episode.emission.title, episode.title)
-
- return JsonResponse({
+ return JsonResponse(
+ {
'results': [
{
'text': fmt(x),
'id': x.pk,
}
for x in queryset
- ],
- 'more': False
- })
-
-
-episodes = EpisodesView.as_view()
+ ],
+ 'more': False,
+ }
+ )
import os
import subprocess
import sys
-
-from setuptools.command.install_lib import install_lib as _install_lib
+from distutils.cmd import Command
from distutils.command.build import build as _build
from distutils.command.sdist import sdist as _sdist
-from distutils.cmd import Command
-from setuptools import setup, find_packages
+
+from setuptools import find_packages, setup
+from setuptools.command.install_lib import install_lib as _install_lib
class sdist(_sdist):
def get_version():
if os.path.exists('VERSION'):
- with open('VERSION', 'r') as v:
+ with open('VERSION') as v:
return v.read()
if os.path.exists('.git'):
- p = subprocess.Popen(['git', 'describe', '--dirty=.dirty', '--match=v*'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ p = subprocess.Popen(
+ ['git', 'describe', '--dirty=.dirty', '--match=v*'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
result = p.communicate()[0]
if p.returncode == 0:
result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v
version = result
return version
else:
- return '0.0.post%s' % len(
- subprocess.check_output(
- ['git', 'rev-list', 'HEAD']).splitlines())
+ return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
return '0.0'
def run(self):
try:
from django.core.management import call_command
+
for path, dirs, files in os.walk('panikombo'):
if 'locale' not in dirs:
continue
'compile_translations': compile_translations,
'install_lib': install_lib,
'sdist': sdist,
- }
+ },
)