From: Guillaume Pellerin Date: Mon, 21 Mar 2016 23:34:41 +0000 (+0100) Subject: add abstract Media and Audio models with automatic URL retrieval X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=9b8e7df9de2417633fa21393122b27a73d3fb55f;p=mezzo.git add abstract Media and Audio models with automatic URL retrieval --- diff --git a/app/festival/admin.py b/app/festival/admin.py index 65918868..df00c8a0 100644 --- a/app/festival/admin.py +++ b/app/festival/admin.py @@ -29,6 +29,16 @@ class VideoAdminDisplayable(DisplayableAdmin): fieldsets = deepcopy(VideoAdmin.fieldsets) +class AudioAdmin(admin.ModelAdmin): + + model = Audio + + +class AudioAdminDisplayable(DisplayableAdmin): + + fieldsets = deepcopy(AudioAdmin.fieldsets) + + class ArtistAdminDisplayable(DisplayableAdmin): fieldsets = deepcopy(ArtistAdmin.fieldsets) @@ -37,3 +47,4 @@ class ArtistAdminDisplayable(DisplayableAdmin): admin.site.register(PageCategory) admin.site.register(Artist, ArtistAdminDisplayable) admin.site.register(Video, VideoAdminDisplayable) +admin.site.register(Audio, AudioAdminDisplayable) diff --git a/app/festival/migrations/0008_auto_20160322_0018.py b/app/festival/migrations/0008_auto_20160322_0018.py new file mode 100644 index 00000000..98de723b --- /dev/null +++ b/app/festival/migrations/0008_auto_20160322_0018.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-03-21 23:18 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import mezzanine.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('mezzanine_agenda', '0003_auto_20160309_1621'), + ('sites', '0002_alter_domain_unique'), + ('festival', '0007_auto_20160309_1441'), + ] + + operations = [ + migrations.CreateModel( + name='Audio', + 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')), + ('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')), + ('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')), + ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')), + ('media_id', models.CharField(max_length=128, verbose_name='media id')), + ('open_source_url', models.URLField(blank=True, max_length=1024, verbose_name='open source URL')), + ('closed_source_url', models.URLField(blank=True, max_length=1024, verbose_name='closed source URL')), + ('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='audios', to='mezzanine_agenda.Event', verbose_name='event')), + ('site', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')), + ], + options={ + 'db_table': 'festival_audios', + 'verbose_name': 'audio', + }, + ), + migrations.AddField( + model_name='video', + name='closed_source_url', + field=models.URLField(blank=True, max_length=1024, verbose_name='closed source URL'), + ), + migrations.AddField( + model_name='video', + name='open_source_url', + field=models.URLField(blank=True, max_length=1024, verbose_name='open source URL'), + ), + ] diff --git a/app/festival/migrations/0009_auto_20160322_0021.py b/app/festival/migrations/0009_auto_20160322_0021.py new file mode 100644 index 00000000..d2be5599 --- /dev/null +++ b/app/festival/migrations/0009_auto_20160322_0021.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-03-21 23:21 +from __future__ import unicode_literals + +from django.db import migrations, models +import mezzanine.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('festival', '0008_auto_20160322_0018'), + ] + + operations = [ + migrations.AddField( + model_name='audio', + name='content_en', + field=mezzanine.core.fields.RichTextField(null=True, verbose_name='Content'), + ), + migrations.AddField( + model_name='audio', + name='content_fr', + field=mezzanine.core.fields.RichTextField(null=True, verbose_name='Content'), + ), + migrations.AddField( + model_name='audio', + name='description_en', + field=models.TextField(blank=True, null=True, verbose_name='Description'), + ), + migrations.AddField( + model_name='audio', + name='description_fr', + field=models.TextField(blank=True, null=True, verbose_name='Description'), + ), + migrations.AddField( + model_name='audio', + name='title_en', + field=models.CharField(max_length=500, null=True, verbose_name='Title'), + ), + migrations.AddField( + model_name='audio', + name='title_fr', + field=models.CharField(max_length=500, null=True, verbose_name='Title'), + ), + ] diff --git a/app/festival/models.py b/app/festival/models.py index 71c892a8..a9b690ab 100644 --- a/app/festival/models.py +++ b/app/festival/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from django.core.urlresolvers import reverse, reverse_lazy +from django.conf import settings from mezzanine.core.models import RichText, Displayable from mezzanine.core.fields import RichTextField, OrderField, FileField @@ -8,13 +9,17 @@ from mezzanine.utils.models import AdminThumbMixin, upload_to from mezzanine_agenda.models import Event +import requests +from pyquery import PyQuery as pq + # import eve.models from .related import SpanningForeignKey app_label = 'festival' - ALIGNMENT_CHOICES = (('left', _('left')), ('right', _('right'))) +MEDIA_BASE_URL = getattr(settings, 'MEDIA_BASE_URL', 'http://medias.ircam.fr/embed/media/') + class MetaCore: @@ -46,6 +51,13 @@ class BaseTitleModel(models.Model): return self.title +class PageCategory(BaseNameModel): + """Page Category""" + + class Meta(MetaCore): + verbose_name = _('page category') + + class Artist(Displayable, RichText, AdminThumbMixin): """Artist""" @@ -76,30 +88,71 @@ class Artist(Displayable, RichText, AdminThumbMixin): return reverse("festival-artist-detail", kwargs={'slug': self.slug}) -class Video(Displayable, RichText): - """Video""" +class Media(Displayable, RichText): + """Media""" - event = models.ForeignKey(Event, related_name='videos', verbose_name=_('event'), blank=True, null=True, on_delete=models.SET_NULL) 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) class Meta(MetaCore): - verbose_name = _('video') - db_table = app_label + '_videos' + abstract = True def __unicode__(self): return self.title @property - def html(self): - #TODO: get html content from medias.ircam.fr with request module - pass + def uri(self): + return MEDIA_BASE_URL + self.media_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()) + self.title = self.q.attr('data-title') + 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'] + + +class Audio(Media): + """Audio""" + + open_source_mime_type = 'audio/ogg' + closed_source_mime_type = 'audio/mp4' + + event = models.ForeignKey(Event, related_name='audios', verbose_name=_('event'), blank=True, null=True, on_delete=models.SET_NULL) + + class Meta(MetaCore): + verbose_name = _('audio') + db_table = app_label + '_audios' def get_absolute_url(self): return reverse("festival-video-detail", kwargs={"slug": self.slug}) -class PageCategory(BaseNameModel): - """Page Category""" +class Video(Media): + """Video""" + + open_source_mime_type = 'video/webm' + closed_source_mime_type = 'video/mp4' + + event = models.ForeignKey(Event, related_name='videos', verbose_name=_('event'), blank=True, null=True, on_delete=models.SET_NULL) class Meta(MetaCore): - verbose_name = _('page category') + verbose_name = _('video') + db_table = app_label + '_videos' + + @property + def html(self): + #TODO: get html content from medias.ircam.fr with request module + pass + + def get_absolute_url(self): + return reverse("festival-video-detail", kwargs={"slug": self.slug}) diff --git a/app/festival/templates/festival/audio_playlist.html b/app/festival/templates/festival/audio_playlist.html new file mode 100644 index 00000000..073ffdaf --- /dev/null +++ b/app/festival/templates/festival/audio_playlist.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + diff --git a/app/festival/templates/festival/playlist.html b/app/festival/templates/festival/playlist.html deleted file mode 100644 index 073ffdaf..00000000 --- a/app/festival/templates/festival/playlist.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/sandbox/local_settings.py b/app/sandbox/local_settings.py index 7121d4a9..7ea53d1d 100644 --- a/app/sandbox/local_settings.py +++ b/app/sandbox/local_settings.py @@ -78,7 +78,7 @@ EVENT_USE_FEATURED_IMAGE = True ADMIN_MENU_ORDER = ( (_("Content"), ("pages.Page", "blog.BlogPost", "mezzanine_agenda.Event", - "festival.Artist", "festival.Video", + "festival.Artist", "festival.Video", "festival.Audio", "generic.ThreadedComment", (_("Media Library"), "fb_browse"),)), (_("Site"), ("sites.Site", "redirects.Redirect", "conf.Setting")), (_("Users"), ("auth.User", "auth.Group",)), diff --git a/app/translations.py b/app/translations.py index 794a7429..e625b9be 100644 --- a/app/translations.py +++ b/app/translations.py @@ -20,3 +20,9 @@ class ArtistTranslationOptions(TranslationOptions): class VideoTranslationOptions(TranslationOptions): fields = ('title', 'description', 'content') + + +@register(Audio) +class AudioTranslationOptions(TranslationOptions): + + fields = ('title', 'description', 'content')