]> git.parisson.com Git - mezzo.git/commitdiff
Unify Audio and Video into Media, then generic Playlist everywhere
authorGuillaume Pellerin <guillaume.pellerin@ircam.fr>
Thu, 13 Oct 2016 14:58:11 +0000 (16:58 +0200)
committerGuillaume Pellerin <guillaume.pellerin@ircam.fr>
Thu, 13 Oct 2016 14:58:11 +0000 (16:58 +0200)
31 files changed:
app/organization/agenda/admin.py
app/organization/agenda/migrations/0009_auto_20161013_1631.py [new file with mode: 0644]
app/organization/agenda/models.py
app/organization/agenda/translation.py
app/organization/magazine/admin.py
app/organization/magazine/migrations/0011_auto_20161013_1631.py [new file with mode: 0644]
app/organization/magazine/migrations/0012_auto_20161013_1631.py [new file with mode: 0644]
app/organization/magazine/models.py
app/organization/magazine/translation.py
app/organization/media/admin.py
app/organization/media/migrations/0006_auto_20161013_1631.py [new file with mode: 0644]
app/organization/media/migrations/0007_auto_20161013_1631.py [new file with mode: 0644]
app/organization/media/models.py
app/organization/media/translation.py
app/organization/media/urls.py
app/organization/media/views.py
app/organization/network/admin.py
app/organization/network/migrations/0038_auto_20161013_1631.py [new file with mode: 0644]
app/organization/network/models.py
app/organization/network/translation.py
app/organization/pages/admin.py
app/organization/pages/forms.py
app/organization/pages/migrations/0008_auto_20161013_1631.py [new file with mode: 0644]
app/organization/pages/models.py
app/organization/pages/translation.py
app/organization/pages/views.py
app/organization/projects/admin.py
app/organization/projects/migrations/0020_auto_20161013_1631.py [new file with mode: 0644]
app/organization/projects/models.py
app/organization/projects/translation.py
app/organization/shop/admin.py

index f5a4d565962307d96ebb788d08b89ba03ee2f5e5..5a1bed381da51252c8a8e2a976f33a06988d9181 100644 (file)
@@ -27,14 +27,9 @@ class EventImageInline(TabularDynamicInlineAdmin):
     model = EventImage
 
 
-class EventAudioInline(StackedDynamicInlineAdmin):
+class EventPlaylistInline(StackedDynamicInlineAdmin):
 
-    model = EventAudio
-
-
-class EventVideoInline(StackedDynamicInlineAdmin):
-
-    model = EventVideo
+    model = EventPlaylist
 
 
 class EventDepartmentInline(TabularDynamicInlineAdmin):
@@ -73,8 +68,8 @@ class CustomEventAdmin(EventAdmin):
     if settings.EVENT_USE_FEATURED_IMAGE:
         list_display.insert(0, "admin_thumb")
     list_filter = deepcopy(DisplayableAdmin.list_filter) + ("location", "category")
-    inlines = [EventPeriodInline, EventBlockInline, EventImageInline, EventDepartmentInline, EventPersonInline,
-                EventLinkInline, EventAudioInline, EventVideoInline, EventTrainingInline]
+    inlines = [EventPeriodInline, EventBlockInline, EventImageInline, EventDepartmentInline,
+                EventPersonInline, EventLinkInline, EventPlaylistInline, EventTrainingInline]
 
     def save_form(self, request, form, change):
         """
diff --git a/app/organization/agenda/migrations/0009_auto_20161013_1631.py b/app/organization/agenda/migrations/0009_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..d3aa4b0
--- /dev/null
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0005_auto_20160930_1849'),
+        ('mezzanine_agenda', '0013_auto_20161010_1130'),
+        ('organization-agenda', '0008_auto_20161005_1455'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='EventPlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+                ('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='mezzanine_agenda.Event', verbose_name='event')),
+            ],
+            options={
+                'verbose_name': 'playlist',
+                'verbose_name_plural': 'playlists',
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.DeleteModel(
+            name='EventAudio',
+        ),
+        migrations.DeleteModel(
+            name='EventVideo',
+        ),
+        migrations.AlterOrderWithRespectTo(
+            name='eventplaylist',
+            order_with_respect_to='event',
+        ),
+    ]
index 4972904e3476b74de06514e445acf934c4d7147c..288f90a35c1ea5f2e3ea86208c265500ec8ef3ec 100644 (file)
@@ -57,23 +57,13 @@ class EventLink(Link):
         verbose_name_plural = _("links")
 
 
-class EventAudio(Audio):
+class EventPlaylist(Playlist):
 
-    event = models.ForeignKey(Event, verbose_name=_('event'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
+    event = models.ForeignKey(Event, verbose_name=_('event'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
     class Meta:
-        verbose_name = _("audio")
-        verbose_name_plural = _("audios")
-        order_with_respect_to = "event"
-
-
-class EventVideo(Video):
-
-    event = models.ForeignKey(Event, verbose_name=_('event'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
-
-    class Meta:
-        verbose_name = _("video")
-        verbose_name_plural = _("videos")
+        verbose_name = _("playlist")
+        verbose_name_plural = _("playlists")
         order_with_respect_to = "event"
 
 
index 7d45af7fb9e5950f0b0dec51aa5f352e8450b7da..8625467279bbb80330fa2975ea0bde0c7c11f700 100644 (file)
@@ -15,14 +15,8 @@ class EventImageTranslationOptions(TranslationOptions):
     fields = ()
 
 
-@register(EventAudio)
-class EventAudioTranslationOptions(TranslationOptions):
-
-    fields = ()
-
-
-@register(EventVideo)
-class EventVideoTranslationOptions(TranslationOptions):
+@register(EventPlaylist)
+class EventPlaylistTranslationOptions(TranslationOptions):
 
     fields = ()
 
index d397a1605a1fce04a51562136bfba301d09d6661..cf7e863c1ef80d462ccf46c5b295c538b964c007 100644 (file)
@@ -12,14 +12,9 @@ class ArticleImageInline(TabularDynamicInlineAdmin):
     model = ArticleImage
 
 
-class ArticleVideoInline(StackedDynamicInlineAdmin):
+class ArticlePlaylistInline(TabularDynamicInlineAdmin):
 
-    model = ArticleVideo
-
-
-class ArticleAudioInline(StackedDynamicInlineAdmin):
-
-    model = ArticleAudio
+    model = ArticlePlaylist
 
 
 class ArticleAdmin(admin.ModelAdmin):
@@ -52,8 +47,7 @@ class ArticleAdminDisplayable(DisplayableAdmin):
     inlines = [ArticleImageInline,
               ArticlePersonAutocompleteInlineAdmin,
               DynamicContentArticleInline,
-              ArticleVideoInline,
-              ArticleAudioInline]
+              ArticlePlaylistInline]
 
 
 class BriefAdmin(admin.ModelAdmin): #OrderableTabularInline
diff --git a/app/organization/magazine/migrations/0011_auto_20161013_1631.py b/app/organization/magazine/migrations/0011_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..cbea17c
--- /dev/null
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0005_auto_20160930_1849'),
+        ('organization-magazine', '0010_articleaudio_articlevideo'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ArticlePlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.RemoveField(
+            model_name='articleaudio',
+            name='article',
+        ),
+        migrations.RemoveField(
+            model_name='articleaudio',
+            name='audio_ptr',
+        ),
+        migrations.RemoveField(
+            model_name='articlevideo',
+            name='article',
+        ),
+        migrations.RemoveField(
+            model_name='articlevideo',
+            name='video_ptr',
+        ),
+    ]
diff --git a/app/organization/magazine/migrations/0012_auto_20161013_1631.py b/app/organization/magazine/migrations/0012_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..0bc550b
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-magazine', '0011_auto_20161013_1631'),
+        ('organization-media', '0006_auto_20161013_1631'),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name='ArticleAudio',
+        ),
+        migrations.DeleteModel(
+            name='ArticleVideo',
+        ),
+        migrations.AddField(
+            model_name='articleplaylist',
+            name='article',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='organization-magazine.Article', verbose_name='article'),
+        ),
+    ]
index 90dba92259bc2cee24456366fca496af67961062..b044f0a524cea0b38384eaeb8af8ae142f349375 100644 (file)
@@ -12,7 +12,7 @@ from mezzanine.core.models import RichText, Displayable, Slugged
 from mezzanine.pages.models import Page
 from mezzanine.blog.models import BlogPost
 from organization.network.models import Department, PersonListBlock
-from organization.media.models import Audio, Video
+from organization.media.models import Playlist
 from organization.core.models import *
 from organization.magazine.apps import *
 
@@ -40,14 +40,9 @@ class ArticleImage(Image):
         order_with_respect_to = "article"
 
 
-class ArticleAudio(Audio):
+class ArticlePlaylist(Playlist):
 
-    article = models.ForeignKey(Article, verbose_name=_('article'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
-
-
-class ArticleVideo(Video):
-
-    article = models.ForeignKey(Article, verbose_name=_('article'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
+    article = models.ForeignKey(Article, verbose_name=_('article'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
 
 class Brief(Displayable, RichText): #Orderable
index ac7b7a098a3c1b7206fe41535959db4d84e0e83b..e52ad434318076635c240097ff25cee13eccba8d 100644 (file)
@@ -43,13 +43,7 @@ class DynamicContentArticleTranslationOptions(TranslationOptions):
     pass
 
 
-@register(ArticleAudio)
-class ArticleAudioTranslationOptions(TranslationOptions):
-
-    pass
-
-
-@register(ArticleVideo)
-class ArticleVideoTranslationOptions(TranslationOptions):
+@register(ArticlePlaylist)
+class ArticlePlaylistTranslationOptions(TranslationOptions):
 
     pass
index 54d87ff1da9afab1550ae89afaace929001849d7..7e20aa10ff3d422a0e0d429245358e86675b95d8 100644 (file)
@@ -4,21 +4,25 @@ from mezzanine.core.admin import *
 from organization.media.models import *
 
 
-class VideoAdmin(BaseTranslationModelAdmin):
+class MediaTranscodedAdmin(TabularDynamicInlineAdmin):
 
-    model = Video
+    model = MediaTranscoded
 
 
-class AudioAdmin(BaseTranslationModelAdmin):
+class MediaAdmin(BaseTranslationModelAdmin):
 
-    model = Audio
+    model = Media
+    inlines = (MediaTranscodedAdmin,)
+
+class PlaylistMediaInline(TabularDynamicInlineAdmin):
+
+    model = PlaylistMedia
 
 
 class PlaylistAdmin(BaseTranslationModelAdmin):
 
     model = Playlist
-    list_display = ('__str__',)
-    filter_horizontal = ['audios']
+    inlines = (PlaylistMediaInline,)
 
 
 class MediaCategoryAdmin(BaseTranslationModelAdmin):
@@ -26,7 +30,6 @@ class MediaCategoryAdmin(BaseTranslationModelAdmin):
     model = MediaCategory
 
 
-admin.site.register(Video, VideoAdmin)
-admin.site.register(Audio, AudioAdmin)
+admin.site.register(Media, MediaAdmin)
 admin.site.register(Playlist, PlaylistAdmin)
 admin.site.register(MediaCategory, MediaCategoryAdmin)
diff --git a/app/organization/media/migrations/0006_auto_20161013_1631.py b/app/organization/media/migrations/0006_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..09cd5b5
--- /dev/null
@@ -0,0 +1,164 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import mezzanine.core.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0005_auto_20160930_1849'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Media',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('keywords_string', models.CharField(blank=True, editable=False, max_length=500)),
+                ('title', models.CharField(max_length=500, verbose_name='Title')),
+                ('title_fr', models.CharField(max_length=500, null=True, verbose_name='Title')),
+                ('title_en', models.CharField(max_length=500, null=True, verbose_name='Title')),
+                ('slug', models.CharField(blank=True, help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL')),
+                ('_meta_title', models.CharField(blank=True, help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title')),
+                ('description', models.TextField(blank=True, verbose_name='Description')),
+                ('description_fr', models.TextField(blank=True, null=True, verbose_name='Description')),
+                ('description_en', models.TextField(blank=True, null=True, verbose_name='Description')),
+                ('gen_description', models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description')),
+                ('created', models.DateTimeField(editable=False, null=True)),
+                ('updated', models.DateTimeField(editable=False, null=True)),
+                ('status', models.IntegerField(choices=[(1, 'Draft'), (2, 'Published')], default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status')),
+                ('publish_date', models.DateTimeField(blank=True, db_index=True, help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from')),
+                ('expiry_date', models.DateTimeField(blank=True, help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on')),
+                ('short_url', models.URLField(blank=True, null=True)),
+                ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')),
+                ('external_id', models.CharField(max_length=128, verbose_name='media id')),
+                ('poster_url', models.URLField(blank=True, max_length=1024, verbose_name='poster')),
+                ('created_at', models.DateTimeField(auto_now=True)),
+            ],
+            options={
+                'verbose_name': 'media',
+                'ordering': ('-created_at',),
+                'verbose_name_plural': 'medias',
+            },
+        ),
+        migrations.CreateModel(
+            name='MediaTranscoded',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('file', mezzanine.core.fields.FileField(max_length=1024, verbose_name='Image')),
+                ('url', models.URLField(blank=True, max_length=1024, verbose_name='URL')),
+                ('mime_type', models.CharField(max_length=64, verbose_name='mime type')),
+            ],
+            options={
+                'verbose_name': 'media',
+                'verbose_name_plural': 'medias',
+            },
+        ),
+        migrations.CreateModel(
+            name='PlaylistMedia',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+            ],
+            options={
+                'verbose_name': 'media',
+                'verbose_name_plural': 'medias',
+            },
+        ),
+        migrations.RemoveField(
+            model_name='audio',
+            name='category',
+        ),
+        migrations.RemoveField(
+            model_name='audio',
+            name='site',
+        ),
+        migrations.RemoveField(
+            model_name='video',
+            name='category',
+        ),
+        migrations.RemoveField(
+            model_name='video',
+            name='site',
+        ),
+        migrations.AlterModelOptions(
+            name='playlist',
+            options={'verbose_name': 'playlist', 'verbose_name_plural': 'playlists'},
+        ),
+        migrations.RemoveField(
+            model_name='playlist',
+            name='audios',
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='_meta_title',
+            field=models.CharField(blank=True, help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='created',
+            field=models.DateTimeField(editable=False, null=True),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='expiry_date',
+            field=models.DateTimeField(blank=True, help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='gen_description',
+            field=models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='in_sitemap',
+            field=models.BooleanField(default=True, verbose_name='Show in sitemap'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='keywords_string',
+            field=models.CharField(blank=True, editable=False, max_length=500),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='publish_date',
+            field=models.DateTimeField(blank=True, db_index=True, help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='short_url',
+            field=models.URLField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='status',
+            field=models.IntegerField(choices=[(1, 'Draft'), (2, 'Published')], default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='type',
+            field=models.CharField(blank=True, choices=[('audio', 'audio'), ('video', 'video')], max_length=32, null=True, verbose_name='type'),
+        ),
+        migrations.AddField(
+            model_name='playlist',
+            name='updated',
+            field=models.DateTimeField(editable=False, null=True),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='description',
+            field=models.TextField(blank=True, verbose_name='Description'),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='description_en',
+            field=models.TextField(blank=True, null=True, verbose_name='Description'),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='description_fr',
+            field=models.TextField(blank=True, null=True, verbose_name='Description'),
+        ),
+    ]
diff --git a/app/organization/media/migrations/0007_auto_20161013_1631.py b/app/organization/media/migrations/0007_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..dc78de0
--- /dev/null
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('sites', '0002_alter_domain_unique'),
+        ('organization-pages', '0008_auto_20161013_1631'),
+        ('organization-magazine', '0012_auto_20161013_1631'),
+        ('organization-media', '0006_auto_20161013_1631'),
+        ('organization-network', '0038_auto_20161013_1631'),
+        ('organization-projects', '0020_auto_20161013_1631'),
+        ('organization-agenda', '0009_auto_20161013_1631'),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name='Audio',
+        ),
+        migrations.DeleteModel(
+            name='Video',
+        ),
+        migrations.AddField(
+            model_name='playlistmedia',
+            name='media',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='organization-media.Media', verbose_name='media'),
+        ),
+        migrations.AddField(
+            model_name='playlistmedia',
+            name='playlist',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='medias', to='organization-media.Playlist', verbose_name='playlist'),
+        ),
+        migrations.AddField(
+            model_name='mediatranscoded',
+            name='media',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transcoded', to='organization-media.Media', verbose_name='media'),
+        ),
+        migrations.AddField(
+            model_name='media',
+            name='category',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='medias', to='organization-media.MediaCategory', verbose_name='category'),
+        ),
+        migrations.AddField(
+            model_name='media',
+            name='site',
+            field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site'),
+        ),
+    ]
index 35fcda665e701578916743a629ab7f80c8e91506..8fd66b3a5f633c355978135d08115c0a15a7e3d0 100644 (file)
@@ -13,78 +13,84 @@ from mezzanine_agenda.models import Event
 from django.conf import settings
 import requests
 
+
 MEDIA_BASE_URL = getattr(settings, 'MEDIA_BASE_URL', 'http://medias.ircam.fr/embed/media/')
 
+PLAYLIST_TYPE_CHOICES = [
+    ('audio', _('audio')),
+    ('video', _('video')),
+]
 
 class Media(Displayable):
     """Media"""
 
-    media_id = models.CharField(_('media id'), max_length=128)
-    open_source_url = models.URLField(_('open source URL'), max_length=1024, blank=True)
-    closed_source_url = models.URLField(_('closed source URL'), max_length=1024, blank=True)
+    external_id = models.CharField(_('media id'), max_length=128)
     poster_url = models.URLField(_('poster'), max_length=1024, blank=True)
     created_at = models.DateTimeField(auto_now=True)
+    category = models.ForeignKey('MediaCategory', verbose_name=_('category'), related_name='medias', blank=True, null=True, on_delete=models.SET_NULL)
 
     # objects = SearchableManager()
     search_fields = ("title",)
 
     class Meta:
-        abstract = True
+        verbose_name = "media"
+        verbose_name_plural = "medias"
+        ordering = ('-created_at',)
 
-    def __unicode__(self):
+    def __str__(self):
         return self.title
 
+    def get_absolute_url(self):
+        return reverse("organization-media-detail", kwargs={"slug": self.slug})
+
     @property
     def uri(self):
-        return MEDIA_BASE_URL + self.media_id
+        return MEDIA_BASE_URL + self.external_id
 
     def get_html(self):
         r = requests.get(self.uri)
         return r.content
 
-    def clean(self):
-        super(Media, self).clean()
-        self.q = pq(self.get_html())
-        sources = self.q('source')
-        for source in sources:
-            if self.open_source_mime_type in source.attrib['type']:
-                self.open_source_url = source.attrib['src']
-            elif self.closed_source_mime_type in source.attrib['type']:
-                self.closed_source_url = source.attrib['src']
-        video = self.q('video')
-        if len(video):
-            if 'poster' in video[0].attrib.keys():
-                self.poster_url = video[0].attrib['poster']
 
+def create_media(instance, created, raw, **kwargs):
+    # Ignore fixtures and saves for existing courses.
+    if not created or raw:
+        return
 
-class Audio(Media):
-    """Audio"""
+    q = pq(instance.get_html())
+    sources = q('source')
 
-    open_source_mime_type = 'audio/ogg'
-    closed_source_mime_type = 'audio/mp4'
-    category = models.ForeignKey('MediaCategory', verbose_name=_('category'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
+    video = q('video')
+    if len(video):
+        if 'poster' in video[0].attrib.keys():
+            instance.poster_url = video[0].attrib['poster']
 
-    class Meta:
-        verbose_name = _('audio')
-        ordering = ('-created_at',)
+    for source in sources:
+        mime_type = source.attrib['type']
+        transcoded = MediaTranscoded(media=instance, mime_type=mime_type)
+        transcoded.url = source.attrib['src']
+        transcoded.save()
 
-    def get_absolute_url(self):
-        return reverse("festival-audio-detail", kwargs={"slug": self.slug})
+    instance.save()
+
+models.signals.post_save.connect(create_media, sender=Media, dispatch_uid='create_media')
 
 
-class Video(Media):
-    """Video"""
+class MediaTranscoded(models.Model):
 
-    open_source_mime_type = 'video/webm'
-    closed_source_mime_type = 'video/mp4'
-    category = models.ForeignKey('MediaCategory', verbose_name=_('category'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
+    media = models.ForeignKey('Media', verbose_name=_('media'), related_name='transcoded')
+    file = FileField(_("Image"), max_length=1024, upload_to="uploads/media/")
+    url = models.URLField(_('URL'), max_length=1024, blank=True)
+    mime_type = models.CharField(_('mime type'), max_length=64)
+
+    preferred_mime_type = ['video/webm', 'audio/ogg']
 
     class Meta:
-        verbose_name = _('video')
-        ordering = ('-created_at',)
+        verbose_name = "media"
+        verbose_name_plural = "medias"
 
-    def get_absolute_url(self):
-        return reverse("festival-video-detail", kwargs={"slug": self.slug})
+    def __str__(self):
+        return self.url
 
 
 class MediaCategory(Slugged, Description):
@@ -95,16 +101,28 @@ class MediaCategory(Slugged, Description):
         verbose_name_plural = _('media categories')
 
     def count(self):
-        try:
-            return self.videos.published().count()+1
-        except:
-            return self.audios.published().count()+1
+        return self.medias.published().count()+1
 
 
-class Playlist(Slugged, Description):
-    """(Playlist description)"""
+class Playlist(Displayable):
+    """Playlist"""
 
-    audios = models.ManyToManyField('Audio', verbose_name=_('audios'), related_name='playlists', blank=True)
+    type = models.CharField(_('type'), max_length=32, choices=PLAYLIST_TYPE_CHOICES, blank=True, null=True)
 
-    def __str__(self):
-        return self.title
+    class Meta:
+        verbose_name = _('playlist')
+        verbose_name_plural = _('playlists')
+
+    def get_absolute_url(self):
+        return reverse("organization-playlist-detail", kwargs={"slug": self.slug})
+
+
+class PlaylistMedia(models.Model):
+    """Playlist media"""
+
+    playlist = models.ForeignKey(Playlist, verbose_name=_('playlist'), related_name='medias', blank=True, null=True, on_delete=models.SET_NULL)
+    media = models.ForeignKey(Media, verbose_name=_('media'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
+
+    class Meta:
+        verbose_name = _('media')
+        verbose_name_plural = _('medias')
index 433dd153b04c72b1b9359cc1ad242b0de9af9f25..0192d9291b8de3150d067bcfbc6e237ff3cbb8e8 100644 (file)
@@ -3,16 +3,16 @@ from modeltranslation.translator import translator, register, TranslationOptions
 from organization.media.models import *
 
 
-@register(Video)
-class VideoTranslationOptions(TranslationOptions):
+@register(Media)
+class MediaTranslationOptions(TranslationOptions):
 
     fields = ('title', 'description',)
 
 
-@register(Audio)
-class AudioTranslationOptions(TranslationOptions):
+@register(MediaTranscoded)
+class MediaTranscodedTranslationOptions(TranslationOptions):
 
-        fields = ('title', 'description',)
+    fields = ()
 
 
 @register(Playlist)
@@ -21,6 +21,12 @@ class PlaylistTranslationOptions(TranslationOptions):
     fields = ('title', 'description',)
 
 
+@register(PlaylistMedia)
+class PlaylistMediaTranslationOptions(TranslationOptions):
+
+    fields = ()
+
+
 @register(MediaCategory)
 class MediaCategoryTranslationOptions(TranslationOptions):
 
index 2e5763d538c524520b37c29d83fae2dfd891e50e..55f1ad05dfe5a2ff2164e0126b51eddc4a0c3ee7 100644 (file)
@@ -11,11 +11,6 @@ from organization.media.views import *
 
 
 urlpatterns = [
-    url(r'^media-list/$', MediaListView.as_view(), name="media-list"),
-    url(r'^videos/$', VideoListView.as_view(), name="festival-video-list"),
-    url(r'^videos/detail/(?P<slug>.*)/$', VideoDetailView.as_view(), name="festival-video-detail"),
-    url(r'^videos/category/(?P<slug>.*)/$', VideoListCategoryView.as_view(), name="festival-video-list-category"),
-    url(r'^audios/detail/(?P<slug>.*)/$', AudioDetailView.as_view(), name="festival-audio-detail"),
-    url(r'^audios/category/(?P<slug>.*)/$', AudioListCategoryView.as_view(), name="festival-audio-list-category"),
-
+    url(r'^playlist/list/$', PlaylistListView.as_view(), name="organization-playlist-list"),
+    url(r'^playlist/detail/(?P<slug>.*)/$', PlaylistDetailView.as_view(), name="organization-playlist-detail"),
 ]
index 4ea5af32d8b765a0a433211f8998e3eac9e7ce34..37616eee0d521bf12543a46e3b2acd91d83c5ddb 100644 (file)
@@ -4,93 +4,32 @@ from organization.media.models import *
 from organization.core.views import *
 from dal import autocomplete
 from dal_select2_queryset_sequence.views import Select2QuerySetSequenceView
-from mezzanine_agenda.models import Event
-from organization.agenda.models import EventVideo
-from organization.magazine.models import Article, Topic, Brief, ArticleVideo
 
 
-class VideoListView(ListView):
+class PlaylistDetailView(SlugMixin, DetailView):
 
-    model = Video
-    template_name='festival/video_list.html'
-
-    def get_queryset(self, **kwargs):
-        return self.model.objects.published()
-
-    def get_context_data(self, **kwargs):
-        context = super(VideoListView, self).get_context_data(**kwargs)
-        context['categories'] = MediaCategory.objects.all()
-        return context
-
-
-class VideoDetailView(SlugMixin, DetailView):
-
-    model = Video
-    template_name='festival/video_detail.html'
-    context_object_name = 'video'
-
-    def get_context_data(self, **kwargs):
-        context = super(VideoDetailView, self).get_context_data(**kwargs)
-        return context
-
-
-class VideoListCategoryView(VideoListView):
-
-    def get_queryset(self):
-        self.category = MediaCategory.objects.get(slug=self.kwargs['slug'])
-        return self.model.objects.filter(category=self.category)
-
-    def get_context_data(self, **kwargs):
-        context = super(VideoListCategoryView, self).get_context_data(**kwargs)
-        context['category'] = self.category
-        return context
-
-
-class MediaListView(ListView):
-
-    template_name='media/media_list.html'
-    context_object_name = 'media'
-
-    def get_queryset(self):
-        audios = Audio.objects.all()
-        videos = Video.objects.all()
-        media_list = [video for video in videos]
-        # media_list += [audio for audio in audios]
-        media_list.sort(key=lambda x: x.created_at, reverse=True)
-
-        return media_list
-
-
-class AudioDetailView(SlugMixin, DetailView):
-
-    model = Audio
-    template_name='festival/video_detail.html'
-    context_object_name = 'video'
+    model = Playlist
+    template_name='media/playlist_detail.html'
+    context_object_name = 'playlist'
 
     def get_context_data(self, **kwargs):
-        context = super(AudioDetailView, self).get_context_data(**kwargs)
+        context = super(PlaylistDetailView, self).get_context_data(**kwargs)
         return context
 
-class AudioListView(ListView):
 
-    model = Audio
-    template_name='festival/video_list.html'
+class PlaylistListView(ListView):
 
-    def get_queryset(self, **kwargs):
-        return self.model.objects.published()
+    template_name='media/playlist_list.html'
+    context_object_name = 'playlists'
 
     def get_context_data(self, **kwargs):
-        context = super(AudioListView, self).get_context_data(**kwargs)
-        context['categories'] = MediaCategory.objects.all()
+        context = super(PlaylistListView, self).get_context_data(**kwargs)
         return context
 
-class AudioListCategoryView(AudioListView):
-
-    def get_queryset(self):
-        self.category = MediaCategory.objects.get(slug=self.kwargs['slug'])
-        return self.model.objects.filter(category=self.category)
-
-    def get_context_data(self, **kwargs):
-        context = super(AudioListCategoryView, self).get_context_data(**kwargs)
-        context['category'] = self.category
-        return context
+    # def get_queryset(self):
+    #     audio_playlists = PlaylistAudio.objects.all()
+    #     video_playlists = PlaylistVideo.objects.all()
+    #     playlist_list = [video_playlist for video_playlist in video_playlists]
+    #     playlist_list += [audio_playlist for audio_playlist in audio_playlists]
+    #     playlist_list.sort(key=lambda x: x.created_at, reverse=True)
+    #     return playlist_list
index cbcd1bfa07d378cc758e48c5329aca6c65367a2d..1877178f32d410b2a56189e4b412c121a5bc3fa6 100644 (file)
@@ -9,17 +9,12 @@ from organization.network.models import *
 from organization.network.forms import *
 from organization.pages.models import *
 from organization.core.admin import *
-from organization.pages.admin import PageImageInline, PageBlockInline, PageAudioInline, PageVideoInline
+from organization.pages.admin import PageImageInline, PageBlockInline, PagePlaylistInline
 
 
-class OrganizationAudioInline(StackedDynamicInlineAdmin):
+class OrganizationPlaylistInline(StackedDynamicInlineAdmin):
 
-    model = OrganizationAudio
-
-
-class OrganizationVideoInline(StackedDynamicInlineAdmin):
-
-    model = OrganizationVideo
+    model = OrganizationPlaylist
 
 
 class OrganizationLinkInline(StackedDynamicInlineAdmin):
@@ -40,16 +35,16 @@ class OrganizationBlockInline(StackedDynamicInlineAdmin):
 class OrganizationAdmin(BaseTranslationModelAdmin):
 
     model = Organization
-    inlines = [ OrganizationAudioInline,
+    inlines = [ OrganizationPlaylistInline,
                 OrganizationImageInline,
-                OrganizationVideoInline,
                 OrganizationBlockInline,
                 OrganizationLinkInline ]
     list_display = ['name', 'admin_thumb']
 
+
 class DepartmentPageAdmin(PageAdmin):
 
-    inlines = [PageImageInline, PageBlockInline, PageAudioInline, PageVideoInline, ]
+    inlines = [PageImageInline, PageBlockInline, PagePlaylistInline, ]
 
 
 class DepartmentAdmin(BaseTranslationModelAdmin):
@@ -65,7 +60,7 @@ class TeamAdmin(BaseTranslationModelAdmin):
 
 class TeamPageAdmin(PageAdmin):
 
-    inlines = [PageImageInline, PageBlockInline, PageAudioInline, PageVideoInline, ]
+    inlines = [PageImageInline, PageBlockInline, PagePlaylistInline, ]
 
 
 class PersonAdminBase(BaseTranslationModelAdmin):
@@ -79,14 +74,9 @@ class PersonActivityInline(StackedDynamicInlineAdmin):
     fk_name = 'person'
 
 
-class PersonAudioInline(StackedDynamicInlineAdmin):
-
-    model = PersonAudio
-
-
-class PersonVideoInline(StackedDynamicInlineAdmin):
+class PersonPlaylistInline(StackedDynamicInlineAdmin):
 
-    model = PersonVideo
+    model = PersonPlaylist
 
 
 class PersonLinkInline(StackedDynamicInlineAdmin):
@@ -113,10 +103,9 @@ class PersonAdmin(BaseTranslationOrderedModelAdmin):
 
     model = Person
     inlines = [PersonActivityInline,
-               PersonAudioInline,
                PersonImageInline,
-               PersonVideoInline,
                PersonBlockInline,
+               PersonPlaylistInline,
                PersonLinkInline,
                PersonFileInline ]
     first_fields = ['last_name', 'first_name', 'title', 'gender', 'user']
diff --git a/app/organization/network/migrations/0038_auto_20161013_1631.py b/app/organization/network/migrations/0038_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..69b215d
--- /dev/null
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0006_auto_20161013_1631'),
+        ('organization-network', '0037_organizationtype_css_class'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='OrganizationPlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+                ('organization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='organization-network.Organization', verbose_name='organization')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.CreateModel(
+            name='PersonPlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+                ('person', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='organization-network.Person', verbose_name='person')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.RemoveField(
+            model_name='organizationaudio',
+            name='audio_ptr',
+        ),
+        migrations.RemoveField(
+            model_name='organizationaudio',
+            name='organization',
+        ),
+        migrations.RemoveField(
+            model_name='organizationvideo',
+            name='organization',
+        ),
+        migrations.RemoveField(
+            model_name='organizationvideo',
+            name='video_ptr',
+        ),
+        migrations.RemoveField(
+            model_name='personaudio',
+            name='audio_ptr',
+        ),
+        migrations.RemoveField(
+            model_name='personaudio',
+            name='person',
+        ),
+        migrations.RemoveField(
+            model_name='personvideo',
+            name='person',
+        ),
+        migrations.RemoveField(
+            model_name='personvideo',
+            name='video_ptr',
+        ),
+        migrations.DeleteModel(
+            name='OrganizationAudio',
+        ),
+        migrations.DeleteModel(
+            name='OrganizationVideo',
+        ),
+        migrations.DeleteModel(
+            name='PersonAudio',
+        ),
+        migrations.DeleteModel(
+            name='PersonVideo',
+        ),
+    ]
index b7028907a4767cb276c4c69da54fe27f9aa5a5e4..01bf36a1161dac065d3fe5add654ff70accbcc8c 100644 (file)
@@ -125,14 +125,9 @@ class Organization(Named, Address, URL, AdminThumbRelatedMixin):
         super(Organization, self).save()
 
 
-class OrganizationAudio(Audio):
+class OrganizationPlaylist(Playlist):
 
-    organization = models.ForeignKey(Organization, verbose_name=_('organization'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
-
-
-class OrganizationVideo(Video):
-
-    organization = models.ForeignKey(Organization, verbose_name=_('organization'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
+    organization = models.ForeignKey(Organization, verbose_name=_('organization'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
 
 class OrganizationLink(Link):
@@ -273,14 +268,9 @@ class Person(Displayable, AdminThumbMixin):
         super(Person, self).save(*args, **kwargs)
 
 
-class PersonAudio(Audio):
-
-    person = models.ForeignKey(Person, verbose_name=_('person'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
-
-
-class PersonVideo(Video):
+class PersonPlaylist(Playlist):
 
-    person = models.ForeignKey(Person, verbose_name=_('person'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
+    person = models.ForeignKey(Person, verbose_name=_('person'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
 
 class PersonLink(Link):
index 9b2bd91bf96104b0d849303cb24863144ae3ae59..7d763d0178afe246c62f11b7fc3fe317d65b79ed 100644 (file)
@@ -45,14 +45,8 @@ class PersonActivityTranslationOptions(TranslationOptions):
     fields = ('comments',)
 
 
-@register(PersonAudio)
-class PersonAudioTranslationOptions(TranslationOptions):
-
-    pass
-
-
-@register(PersonVideo)
-class PersonVideoTranslationOptions(TranslationOptions):
+@register(PersonPlaylist)
+class PersonPlaylistTranslationOptions(TranslationOptions):
 
     pass
 
@@ -81,14 +75,8 @@ class PersonBlockTranslationOptions(TranslationOptions):
     pass
 
 
-@register(OrganizationAudio)
-class OrganizationAudioTranslationOptions(TranslationOptions):
-
-    pass
-
-
-@register(OrganizationVideo)
-class OrganizationVideoTranslationOptions(TranslationOptions):
+@register(OrganizationPlaylist)
+class OrganizationTranslationOptions(TranslationOptions):
 
     pass
 
index db5d01c086c78a3050ce008993cb775cf42016c2..cb04bfeefa3f38010fe5db114761dd8f8c2dfb9f 100644 (file)
@@ -26,15 +26,9 @@ class PageImageInline(TabularDynamicInlineAdmin):
     model = PageImage
 
 
-class PageAudioInline(StackedDynamicInlineAdmin):
+class PagePlaylistInline(StackedDynamicInlineAdmin):
 
-    model = PageAudio
-    exclude = ("short_url", "keywords", "description", "slug", )
-
-
-class PageVideoInline(StackedDynamicInlineAdmin):
-
-    model = PageVideo
+    model = PagePlaylist
     exclude = ("short_url", "keywords", "description", "slug", )
 
 
@@ -79,8 +73,7 @@ class CustomPageAdmin(PageAdmin):
 
     inlines = [PageBlockInline,
             PageImageInline,
-            PageAudioInline,
-            PageVideoInline,
+            PagePlaylistInline,
             PageLinkInline,
             PersonListBlockAutocompleteInlineAdmin,
             PageProductListInline,
index e82ada1f10ecc6d7864cd275230d5d1f777de6fb..a8a2d7d56e20386348572985b7b96dfa6ccb52e3 100644 (file)
@@ -11,7 +11,8 @@ from organization.magazine.models import Article, Topic, Brief
 from organization.pages.models import CustomPage
 from organization.pages.models import *
 from organization.agenda.models import Event
-from organization.media.models import Audio, Video
+from organization.media.models import Playlist
+
 
 class DynamicContentHomeSliderForm(autocomplete.FutureModelForm):
 
@@ -52,8 +53,7 @@ class DynamicContentHomeMediaForm(autocomplete.FutureModelForm):
 
     content_object = dal_queryset_sequence.fields.QuerySetSequenceModelField(
         queryset=autocomplete.QuerySetSequence(
-            Audio.objects.all(),
-            Video.objects.all(),
+            Playlist.objects.all(),
         ),
         required=False,
         widget=dal_select2_queryset_sequence.widgets.QuerySetSequenceSelect2('dynamic-content-home-media'),
diff --git a/app/organization/pages/migrations/0008_auto_20161013_1631.py b/app/organization/pages/migrations/0008_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..9734838
--- /dev/null
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0006_auto_20161013_1631'),
+        ('pages', '0005_auto_20160923_1219'),
+        ('organization-pages', '0007_auto_20161007_1852'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='PagePlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+                ('page', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='pages.Page', verbose_name='page')),
+            ],
+            options={
+                'verbose_name': 'playlist',
+                'verbose_name_plural': 'playlists',
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.DeleteModel(
+            name='PageAudio',
+        ),
+        migrations.DeleteModel(
+            name='PageVideo',
+        ),
+        migrations.AlterOrderWithRespectTo(
+            name='pageplaylist',
+            order_with_respect_to='page',
+        ),
+    ]
index 02047b1928df026ea6d1a50ffebaba5f3a2fd8d9..b9b8d5b3c5db53690bb6a0da37ec5e2995c4ad91 100644 (file)
@@ -33,23 +33,13 @@ class PageImage(Image):
         order_with_respect_to = "page"
 
 
-class PageAudio(Audio):
+class PagePlaylist(Playlist):
 
-    page = models.ForeignKey(Page, verbose_name=_('page'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
+    page = models.ForeignKey(Page, verbose_name=_('page'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
     class Meta:
-        verbose_name = _("audio")
-        verbose_name_plural = _("audios")
-        order_with_respect_to = "page"
-
-
-class PageVideo(Video):
-
-    page = models.ForeignKey(Page, verbose_name=_('page'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
-
-    class Meta:
-        verbose_name = _("video")
-        verbose_name_plural = _("videos")
+        verbose_name = _("playlist")
+        verbose_name_plural = _("playlists")
         order_with_respect_to = "page"
 
 
index d6863648c449e6672840abd597c110df135a99cb..79010de94871310b8b077afa9ff471d4617557bc 100644 (file)
@@ -46,14 +46,8 @@ class PageImageTranslationOptions(TranslationOptions):
     fields = ('description',)
 
 
-@register(PageVideo)
-class PageVideoTranslationOptions(TranslationOptions):
-
-    pass
-
-
-@register(PageAudio)
-class PageAudioTranslationOptions(TranslationOptions):
+@register(PagePlaylist)
+class PagePlaylistTranslationOptions(TranslationOptions):
 
     pass
 
index 384acf54dde402d2e312ba08d5e20645eb9eb702..2f5ac05dc2e2f43e1d999a7a1c4a9915e3f2a3aa 100644 (file)
@@ -11,7 +11,7 @@ from organization.core.views import SlugMixin
 from organization.magazine.models import Article, Topic, Brief
 from organization.pages.models import Home
 from organization.agenda.models import Event
-from organization.media.models import Audio, Video
+from organization.media.models import Playlist
 
 
 class HomeView(SlugMixin, ListView):
@@ -91,14 +91,12 @@ class DynamicContentHomeMediaView(Select2QuerySetSequenceView):
 
     def get_queryset(self):
 
-        videos = Video.objects.all()
-        audios = Audio.objects.all()
+        playlists = Playlist.objects.all()
 
         if self.q:
-            videos = videos.filter(title__icontains=self.q)
-            audios = audios.filter(title__icontains=self.q)
+            playlists = videos.filter(title__icontains=self.q)
 
-        qs = autocomplete.QuerySetSequence(videos, audios,)
+        qs = autocomplete.QuerySetSequence(playlists,)
 
         if self.q:
             qs = qs.filter(title__icontains=self.q)
index e2932d268a08aabb587a7b1fb97177e10a6840e2..b217e5461b4efc4da2ead70291fba087c9f13b9f 100644 (file)
@@ -8,7 +8,7 @@ from mezzanine.pages.admin import PageAdmin
 
 from organization.projects.models import *
 from organization.pages.models import *
-from organization.media.models import Video, Audio
+from organization.media.models import Playlist
 
 
 class ProjectLinkInline(StackedDynamicInlineAdmin):
@@ -26,14 +26,9 @@ class ProjectBlockInline(StackedDynamicInlineAdmin):
     model = ProjectBlock
 
 
-class ProjectAudioInline(StackedDynamicInlineAdmin):
+class ProjectPlaylistInline(StackedDynamicInlineAdmin):
 
-    model = ProjectAudio
-
-
-class ProjectVideoInline(StackedDynamicInlineAdmin):
-
-    model = ProjectVideo
+    model = ProjectPlaylist
 
 
 class ProjectFileInline(TabularDynamicInlineAdmin):
@@ -51,8 +46,7 @@ class ProjectAdminDisplayable(DisplayableAdmin):
     fieldsets = deepcopy(ProjectAdmin.fieldsets)
     inlines = [ ProjectBlockInline,
                 ProjectImageInline,
-                ProjectAudioInline,
-                ProjectVideoInline,
+                ProjectPlaylistInline,
                 ProjectLinkInline,
                 ProjectFileInline]
     filter_horizontal = ['teams', 'organizations']
diff --git a/app/organization/projects/migrations/0020_auto_20161013_1631.py b/app/organization/projects/migrations/0020_auto_20161013_1631.py
new file mode 100644 (file)
index 0000000..3c38681
--- /dev/null
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-10-13 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-media', '0006_auto_20161013_1631'),
+        ('organization-projects', '0019_auto_20161007_1045'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ProjectPlaylist',
+            fields=[
+                ('playlist_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='organization-media.Playlist')),
+                ('project', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='playlists', to='organization-projects.Project', verbose_name='project')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('organization-media.playlist',),
+        ),
+        migrations.RemoveField(
+            model_name='projectaudio',
+            name='audio_ptr',
+        ),
+        migrations.RemoveField(
+            model_name='projectaudio',
+            name='project',
+        ),
+        migrations.RemoveField(
+            model_name='projectvideo',
+            name='project',
+        ),
+        migrations.RemoveField(
+            model_name='projectvideo',
+            name='video_ptr',
+        ),
+        migrations.DeleteModel(
+            name='ProjectAudio',
+        ),
+        migrations.DeleteModel(
+            name='ProjectVideo',
+        ),
+    ]
index 5666539b0c3e58b6664f09c65788c9309b1190d9..38d14adb6c3bb57d2df62bee2399e2bd43664508 100644 (file)
@@ -79,14 +79,9 @@ class ProjectProgramType(Named):
         ordering = ['name',]
 
 
-class ProjectAudio(Audio):
+class ProjectPlaylist(Playlist):
 
-    project = models.ForeignKey(Project, verbose_name=_('project'), related_name='audios', blank=True, null=True, on_delete=models.SET_NULL)
-
-
-class ProjectVideo(Video):
-
-    project = models.ForeignKey(Project, verbose_name=_('project'), related_name='videos', blank=True, null=True, on_delete=models.SET_NULL)
+    project = models.ForeignKey(Project, verbose_name=_('project'), related_name='playlists', blank=True, null=True, on_delete=models.SET_NULL)
 
 
 class ProjectLink(Link):
index fea7a757e074651296f8901970691aee846e4b5b..6183b36ab4a83a810e03770ef7d6ab42a6589115 100644 (file)
@@ -9,14 +9,8 @@ class ProjectTranslationOptions(TranslationOptions):
     fields = ('title', 'description', 'content')
 
 
-@register(ProjectVideo)
-class ProjectVideoTranslationOptions(TranslationOptions):
-
-    pass
-
-
-@register(ProjectAudio)
-class ProjectAudioTranslationOptions(TranslationOptions):
+@register(ProjectPlaylist)
+class ProjectPlaylistTranslationOptions(TranslationOptions):
 
     pass
 
index cc66060dd18c4584f1f25363200026cb5b012d19..fb5f2eb0855c1869ec0aa90d3b0bcbb58afcd5fd 100644 (file)
@@ -8,7 +8,6 @@ from mezzanine.core.admin import *
 from organization.core.admin import *
 from organization.projects.models import *
 from organization.pages.models import *
-from organization.media.models import Video, Audio
 from organization.shop.models import *
 
 from cartridge.shop.admin import *