]> git.parisson.com Git - mezzo.git/commitdiff
add featured app, reorganize models and views
authorGuillaume Pellerin <guillaume.pellerin@ircam.fr>
Thu, 7 Jul 2016 14:18:24 +0000 (16:18 +0200)
committerGuillaume Pellerin <guillaume.pellerin@ircam.fr>
Thu, 7 Jul 2016 14:18:24 +0000 (16:18 +0200)
57 files changed:
app/organization/core/management/__init__.py [new file with mode: 0644]
app/organization/core/management/commands/__init__.py [new file with mode: 0644]
app/organization/core/management/commands/create-admin-user.py [new file with mode: 0644]
app/organization/core/management/commands/festival-sync-eve-events.py [new file with mode: 0644]
app/organization/core/management/commands/wait-for-db.py [new file with mode: 0644]
app/organization/core/migrations/0002_auto_20160707_1614.py [new file with mode: 0644]
app/organization/core/models.py
app/organization/core/templatetags/organization_tags.py [new file with mode: 0644]
app/organization/core/views.py
app/organization/featured/__init__.py [new file with mode: 0644]
app/organization/featured/admin.py [new file with mode: 0644]
app/organization/featured/apps.py [new file with mode: 0644]
app/organization/featured/migrations/0001_initial.py [new file with mode: 0644]
app/organization/featured/migrations/0002_auto_20160707_1614.py [new file with mode: 0644]
app/organization/featured/migrations/__init__.py [new file with mode: 0644]
app/organization/featured/models.py [new file with mode: 0644]
app/organization/featured/templatetags/featured_tags.py [new file with mode: 0644]
app/organization/featured/tests.py [new file with mode: 0644]
app/organization/featured/views.py [new file with mode: 0644]
app/organization/festival/admin.py
app/organization/festival/management/__init__.py [deleted file]
app/organization/festival/management/commands/__init__.py [deleted file]
app/organization/festival/management/commands/create-admin-user.py [deleted file]
app/organization/festival/management/commands/festival-sync-eve-events.py [deleted file]
app/organization/festival/management/commands/wait-for-db.py [deleted file]
app/organization/festival/migrations/0001_initial.py
app/organization/festival/models.py
app/organization/festival/templatetags/festival_tags.py
app/organization/festival/translation.py
app/organization/festival/urls.py
app/organization/festival/views.py
app/organization/magazine/admin.py
app/organization/magazine/models.py
app/organization/media/admin.py
app/organization/media/migrations/0001_initial.py [new file with mode: 0644]
app/organization/media/models.py
app/organization/media/translation.py [new file with mode: 0644]
app/organization/media/urls.py [new file with mode: 0644]
app/organization/media/views.py
app/organization/structure/migrations/0002_auto_20160707_1614.py [new file with mode: 0644]
app/organization/structure/models.py
app/settings.py
app/templates/agenda/event_booking.html
app/templates/agenda/event_detail.html
app/templates/agenda/event_iframe.html
app/templates/agenda/includes/event_metainfo.html
app/templates/agenda/includes/event_metainfo_slider.html
app/templates/base.html
app/templates/blog/blog_post_detail.html
app/templates/includes/slider.html
app/templates/index.html
app/templates/pages/basicpage.html
app/templates/pages/page.html
app/templates/styles.html
app/templates/templates/festival/artist_detail.html
app/templates/templates/festival/video_list.html
doc/__init__.py [new file with mode: 0644]

diff --git a/app/organization/core/management/__init__.py b/app/organization/core/management/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/app/organization/core/management/commands/__init__.py b/app/organization/core/management/commands/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/app/organization/core/management/commands/create-admin-user.py b/app/organization/core/management/commands/create-admin-user.py
new file mode 100644 (file)
index 0000000..e7e3cad
--- /dev/null
@@ -0,0 +1,24 @@
+from optparse import make_option
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.contrib.auth.models import User
+
+
+class Command(BaseCommand):
+    help = """Create a default admin user if it doesn't exist.
+            you SHOULD change the password and the email afterwards!"""
+
+    username = 'admin'
+    password = 'admin'
+    email = 'root@example.com'
+
+    def handle(self, *args, **options):
+        admin = User.objects.filter(username=self.username)
+        if not admin:
+            user = User(username=self.username)
+            user.set_password(self.password)
+            user.email = self.email
+            user.is_superuser = True
+            user.is_staff = True
+            user.save()
+            print('User ' + self.username + ' created')
diff --git a/app/organization/core/management/commands/festival-sync-eve-events.py b/app/organization/core/management/commands/festival-sync-eve-events.py
new file mode 100644 (file)
index 0000000..070cadb
--- /dev/null
@@ -0,0 +1,86 @@
+from datetime import datetime, timedelta
+from optparse import make_option
+
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.contrib.auth.models import User
+from django.core.mail import EmailMessage
+
+import mezzanine_agenda.models as ma_models
+from mezzanine.generic.models import AssignedKeyword, Keyword
+
+import eve.models as eve_models
+
+
+class Command(BaseCommand):
+    """Synchronize events from E-vement to mezzanine_agenda"""
+
+
+    option_list = BaseCommand.option_list + (
+          make_option('-m', '--meta_event',
+            dest='meta_event',
+            help='define eve meta_event'),
+          )
+
+    default_user = User.objects.get(username='admin')
+
+    def cleanup(self):
+        # for event in ma_models.Event.objects.all():
+        #     event.delete()
+        # for location in ma_models.EventLocation.objects.all():
+        #     location.delete()
+        for event_price in ma_models.EventPrice.objects.all():
+            event_price.delete()
+
+    def handle(self, *args, **kwargs):
+        # self.cleanup()
+        meta_event_name = kwargs.get('meta_event')
+        meta_trans_all = eve_models.MetaEventTranslation.objects.all()
+        for meta_trans in meta_trans_all:
+            if meta_trans.name == meta_event_name:
+                break
+        eve_events = eve_models.Event.objects.filter(meta_event=meta_trans.id)
+        for eve_event in eve_events:
+            event_trans = eve_models.EventTranslation.objects.filter(id=eve_event, lang='fr')[0]
+            manifestations = eve_event.manifestations.all().order_by('happens_at')
+            first = True
+            for manifestation in manifestations:
+                events = ma_models.Event.objects.filter(external_id=manifestation.id)
+                if not events:
+                    event = ma_models.Event(external_id=manifestation.id)
+                else:
+                    event = events[0]
+                event.start = manifestation.happens_at
+                event.end = manifestation.happens_at + timedelta(seconds=manifestation.duration)
+                event.title = event_trans.name
+                event.user = self.default_user
+
+                locations = ma_models.EventLocation.objects.filter(title=manifestation.location.name)
+                if locations:
+                    location = locations[0]
+                else:
+                    location = ma_models.EventLocation(title=manifestation.location.name)
+                address = '\n'.join([manifestation.location.address, manifestation.location.postalcode + ' ' + manifestation.location.city])
+                location.address = address
+                location.external_id = manifestation.id
+                location.clean()
+                location.save()
+                event.location = location
+                event.save()
+                keyword, _ = Keyword.objects.get_or_create(title=eve_event.event_category.name)
+                event.keywords.add(AssignedKeyword(keyword=keyword), bulk=False)
+
+                eve_prices = eve_models.PriceManifestation.objects.filter(manifestation=manifestation)
+                for price in eve_prices:
+                    event_price, c = ma_models.EventPrice.objects.get_or_create(value=float(price.value))
+                    if event:
+                        if not event_price in event.prices.all():
+                            event.prices.add(event_price)
+
+                if not first:
+                    event.parent = parent
+                else:
+                    parent = event
+                    first = False
+
+                event.save()
diff --git a/app/organization/core/management/commands/wait-for-db.py b/app/organization/core/management/commands/wait-for-db.py
new file mode 100644 (file)
index 0000000..e2bacf0
--- /dev/null
@@ -0,0 +1,30 @@
+import os, time
+
+from optparse import make_option
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.db import connections
+
+
+class Command(BaseCommand):
+    help = "wait for default DB connection"
+
+    db_name = 'default'
+    N = 20
+
+    def handle(self, *args, **options):
+        i = 0
+        connected = False
+        db_conn = connections[self.db_name]
+        while not connected:
+            try:
+                c = db_conn.cursor()
+                connected = True
+            except:
+                print('error connecting to DB...')
+                if i > self.N:
+                    print('...exiting')
+                    raise
+                print('...retrying')
+                i += 1
+                time.sleep(1)
diff --git a/app/organization/core/migrations/0002_auto_20160707_1614.py b/app/organization/core/migrations/0002_auto_20160707_1614.py
new file mode 100644 (file)
index 0000000..5cebb5f
--- /dev/null
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-07-07 14:14
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_alignment',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_card',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_card_credits',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_credits',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_description',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_slider',
+        ),
+        migrations.RemoveField(
+            model_name='basicpage',
+            name='photo_slider_credits',
+        ),
+    ]
index 885583a4d2903dd4bd391183fdc8517f5e7d6b9a..c0d3ae043dc8cf17eacfabdd32000a68f4032f4f 100644 (file)
@@ -1,15 +1,10 @@
 from django.db import models
+from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse, reverse_lazy
+
 from mezzanine.pages.models import Page, RichText
 from mezzanine.core.fields import RichTextField, OrderField, FileField
-from django.conf import settings
-
-from organization.media.models import Photos
-
-ALIGNMENT_CHOICES = (('left', _('left')), ('right', _('right')))
-MEDIA_BASE_URL = getattr(settings, 'MEDIA_BASE_URL', 'http://medias.ircam.fr/embed/media/')
-
 
 
 class Named(models.Model):
@@ -29,6 +24,19 @@ class Named(models.Model):
         return slugify(self.__unicode__())
 
 
+class Titled(models.Model):
+    """Base object with title and description"""
+
+    title = models.CharField(_('title'), max_length=512)
+    description = models.TextField(_('description'), blank=True)
+
+    class Meta:
+        abstract = True
+
+    def __unicode__(self):
+        return self.title
+
+
 class SubTitle(models.Model):
 
     sub_title = models.TextField(_('sub title'), blank=True, max_length=1024)
@@ -37,7 +45,7 @@ class SubTitle(models.Model):
         abstract = True
 
 
-class BasicPage(Page, RichText, SubTitle, Photos):
+class BasicPage(Page, RichText, SubTitle):
 
     class Meta:
         verbose_name = 'basic page'
diff --git a/app/organization/core/templatetags/organization_tags.py b/app/organization/core/templatetags/organization_tags.py
new file mode 100644 (file)
index 0000000..5f3c958
--- /dev/null
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+from mezzanine.pages.models import Page
+from mezzanine.blog.models import BlogPost
+from mezzanine.template import Library
+from mezzanine_agenda.models import Event
+from mezzanine.conf import settings
+from random import shuffle
+
+from organization.festival.models import *
+from organization.magazine.models import *
+
+register = Library()
+
+
+@register.filter
+def subtract(value, arg):
+    return value - arg
+
+@register.as_tag
+def featured_edito(*args):
+    qs = Page.objects.filter(slug="edito")
+    if qs:
+        return qs[0].get_content_model()
+    else:
+        return None
+
+@register.as_tag
+def featured_events(*args):
+    featured = Featured.objects.all()
+    if featured:
+        return featured[0].events.order_by('start')
+    return None
+
+@register.as_tag
+def featured(*args):
+    featured_list = []
+    featured = Featured.objects.filter(id=settings.HOME_FEATURED_ID)
+    if featured:
+        featured = featured[0]
+        for post in featured.blogposts.all():
+            featured_list.append(post)
+        for video in featured.videos.all():
+            featured_list.append(video)
+        for artist in featured.artists.all():
+            featured_list.append(artist)
+        for playlist in featured.playlists.all():
+            featured_list.append(playlist)
+        shuffle(featured_list)
+    return featured_list
+
+@register.as_tag
+def featured_breaking_news_content(*args):
+    featured = Featured.objects.filter(id=settings.BREAKING_NEWS_FEATURED_ID)
+    if featured:
+        featured = featured[0]
+        news = featured.pages.all()
+        if news:
+            return news[0].richtextpage.content
+        else:
+            return ''
+    return ''
+
+@register.filter
+def get_class(obj):
+    return obj.__class__.__name__
+
+@register.filter
+def unique_posts(events):
+    post_list = []
+    for event in events:
+        for post in event.blog_posts.all():
+            print(post)
+            if not post in post_list:
+                post_list.append(post)
+    return post_list
+
+@register.filter
+def no_parents(events):
+    return events.filter(parent=None)
index 91ea44a218fbd2f408430959283f0419c921093e..34f51cd60690e6700b171f2cf8234480de285dad 100644 (file)
@@ -1,3 +1,8 @@
 from django.shortcuts import render
 
-# Create your views here.
+
+class SlugMixin(object):
+
+    def get_object(self):
+        objects = self.model.objects.all()
+        return get_object_or_404(objects, slug=self.kwargs['slug'])
diff --git a/app/organization/featured/__init__.py b/app/organization/featured/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/app/organization/featured/admin.py b/app/organization/featured/admin.py
new file mode 100644 (file)
index 0000000..1318a91
--- /dev/null
@@ -0,0 +1,13 @@
+from django.contrib import admin
+
+from organization.featured.models import *
+
+
+class FeaturedAdmin(admin.ModelAdmin):
+
+    model = Featured
+    list_display = ('__unicode__',)
+    filter_horizontal = ['events', 'videos', 'articles', 'pages', 'playlists']
+
+
+admin.site.register(Featured, FeaturedAdmin)
diff --git a/app/organization/featured/apps.py b/app/organization/featured/apps.py
new file mode 100644 (file)
index 0000000..10cae19
--- /dev/null
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class FeaturedConfig(AppConfig):
+    name = 'featured'
diff --git a/app/organization/featured/migrations/0001_initial.py b/app/organization/featured/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..00bd148
--- /dev/null
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-07-07 14:14
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('organization magazine', '0002_article'),
+        ('mezzanine_agenda', '0014_event_brochure'),
+        ('organization core', '0002_auto_20160707_1614'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Featured',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=512, verbose_name='name')),
+                ('description', models.TextField(blank=True, verbose_name='description')),
+                ('articles', models.ManyToManyField(blank=True, related_name='featured', to='organization magazine.Article', verbose_name='articles')),
+                ('events', models.ManyToManyField(blank=True, related_name='featured', to='mezzanine_agenda.Event', verbose_name='events')),
+                ('pages', models.ManyToManyField(blank=True, related_name='featured', to='organization core.BasicPage', verbose_name='pages')),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+    ]
diff --git a/app/organization/featured/migrations/0002_auto_20160707_1614.py b/app/organization/featured/migrations/0002_auto_20160707_1614.py
new file mode 100644 (file)
index 0000000..2816f5c
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-07-07 14:14
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('featured', '0001_initial'),
+        ('organization media', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='featured',
+            name='playlists',
+            field=models.ManyToManyField(blank=True, related_name='featured', to='organization media.Playlist', verbose_name='playlists'),
+        ),
+        migrations.AddField(
+            model_name='featured',
+            name='videos',
+            field=models.ManyToManyField(blank=True, related_name='featured', to='organization media.Video', verbose_name='videos'),
+        ),
+    ]
diff --git a/app/organization/featured/migrations/__init__.py b/app/organization/featured/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/app/organization/featured/models.py b/app/organization/featured/models.py
new file mode 100644 (file)
index 0000000..ae59ea4
--- /dev/null
@@ -0,0 +1,25 @@
+from __future__ import unicode_literals
+
+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 organization.core.models import *
+from organization.magazine.models import *
+from organization.media.models import *
+
+from mezzanine_agenda.models import Event
+
+
+class Featured(Named):
+    """(Featured description)"""
+
+    pages = models.ManyToManyField(BasicPage, verbose_name=_('pages'), related_name='featured', blank=True)
+    articles = models.ManyToManyField(Article, verbose_name=_('articles'), related_name='featured', blank=True)
+    events = models.ManyToManyField(Event, verbose_name=_('events'), related_name='featured', blank=True)
+    videos = models.ManyToManyField(Video, verbose_name=_('videos'), related_name='featured', blank=True)
+    playlists = models.ManyToManyField(Playlist, verbose_name=_('playlists'), related_name='featured', blank=True)
+
+    def __unicode__(self):
+        return self.name
diff --git a/app/organization/featured/templatetags/featured_tags.py b/app/organization/featured/templatetags/featured_tags.py
new file mode 100644 (file)
index 0000000..79e3267
--- /dev/null
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+from mezzanine.pages.models import Page
+from mezzanine.blog.models import BlogPost
+from mezzanine.template import Library
+from mezzanine_agenda.models import Event
+from mezzanine.conf import settings
+from random import shuffle
+
+from organization.festival.models import *
+from organization.featured.models import *
+
+register = Library()
+
+
+@register.filter
+def subtract(value, arg):
+    return value - arg
+
+@register.as_tag
+def featured_edito(*args):
+    qs = Page.objects.filter(slug="edito")
+    if qs:
+        return qs[0].get_content_model()
+    else:
+        return None
+
+@register.as_tag
+def featured_events(*args):
+    featured = Featured.objects.all()
+    if featured:
+        return featured[0].events.order_by('start')
+    return None
+
+@register.as_tag
+def featured(*args):
+    featured_list = []
+    featured = Featured.objects.filter(id=settings.HOME_FEATURED_ID)
+    if featured:
+        featured = featured[0]
+        for post in featured.blogposts.all():
+            featured_list.append(post)
+        for video in featured.videos.all():
+            featured_list.append(video)
+        for artist in featured.artists.all():
+            featured_list.append(artist)
+        for playlist in featured.playlists.all():
+            featured_list.append(playlist)
+        shuffle(featured_list)
+    return featured_list
+
+@register.as_tag
+def featured_breaking_news_content(*args):
+    featured = Featured.objects.filter(id=settings.BREAKING_NEWS_FEATURED_ID)
+    if featured:
+        featured = featured[0]
+        news = featured.pages.all()
+        if news:
+            return news[0].richtextpage.content
+        else:
+            return ''
+    return ''
+
+@register.filter
+def get_class(obj):
+    return obj.__class__.__name__
+
+@register.filter
+def unique_posts(events):
+    post_list = []
+    for event in events:
+        for post in event.blog_posts.all():
+            print(post)
+            if not post in post_list:
+                post_list.append(post)
+    return post_list
+
+@register.filter
+def no_parents(events):
+    return events.filter(parent=None)
diff --git a/app/organization/featured/tests.py b/app/organization/featured/tests.py
new file mode 100644 (file)
index 0000000..7ce503c
--- /dev/null
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/app/organization/featured/views.py b/app/organization/featured/views.py
new file mode 100644 (file)
index 0000000..91ea44a
--- /dev/null
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
index 70fb8fcc6c2f72748d97b08046ef8d7e31847ad4..eac37c673cc278ec418bb9f4b4ab8080dd2a72e5 100644 (file)
@@ -19,50 +19,9 @@ class ArtistAdmin(admin.ModelAdmin):
     model = Artist
 
 
-class VideoAdmin(admin.ModelAdmin):
-
-    model = Video
-
-
-class VideoAdminDisplayable(DisplayableAdmin):
-
-    fieldsets = deepcopy(VideoAdmin.fieldsets)
-    filter_horizontal = ['artists']
-
-
-class AudioAdmin(admin.ModelAdmin):
-
-    model = Audio
-
-
-class AudioAdminDisplayable(DisplayableAdmin):
-
-    fieldsets = deepcopy(AudioAdmin.fieldsets)
-    filter_horizontal = ['artists']
-
-
 class ArtistAdminDisplayable(DisplayableAdmin):
 
     fieldsets = deepcopy(ArtistAdmin.fieldsets)
 
 
-class PlaylistAdmin(admin.ModelAdmin):
-
-    model = Playlist
-    list_display = ('__unicode__',)
-    filter_horizontal = ['audios']
-
-
-class FeaturedAdmin(admin.ModelAdmin):
-
-    model = Featured
-    list_display = ('__unicode__',)
-    filter_horizontal = ['artists', 'events', 'videos', 'pages', 'blogposts', 'pages', 'playlists']
-
-
 admin.site.register(Artist, ArtistAdminDisplayable)
-admin.site.register(Video, VideoAdminDisplayable)
-admin.site.register(Audio, AudioAdminDisplayable)
-admin.site.register(Playlist, PlaylistAdmin)
-admin.site.register(Featured, FeaturedAdmin)
-admin.site.register(VideoCategory)
diff --git a/app/organization/festival/management/__init__.py b/app/organization/festival/management/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/app/organization/festival/management/commands/__init__.py b/app/organization/festival/management/commands/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/app/organization/festival/management/commands/create-admin-user.py b/app/organization/festival/management/commands/create-admin-user.py
deleted file mode 100644 (file)
index e7e3cad..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-from optparse import make_option
-from django.conf import settings
-from django.core.management.base import BaseCommand, CommandError
-from django.contrib.auth.models import User
-
-
-class Command(BaseCommand):
-    help = """Create a default admin user if it doesn't exist.
-            you SHOULD change the password and the email afterwards!"""
-
-    username = 'admin'
-    password = 'admin'
-    email = 'root@example.com'
-
-    def handle(self, *args, **options):
-        admin = User.objects.filter(username=self.username)
-        if not admin:
-            user = User(username=self.username)
-            user.set_password(self.password)
-            user.email = self.email
-            user.is_superuser = True
-            user.is_staff = True
-            user.save()
-            print('User ' + self.username + ' created')
diff --git a/app/organization/festival/management/commands/festival-sync-eve-events.py b/app/organization/festival/management/commands/festival-sync-eve-events.py
deleted file mode 100644 (file)
index 070cadb..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-from datetime import datetime, timedelta
-from optparse import make_option
-
-from django.conf import settings
-from django.core.management.base import BaseCommand, CommandError
-from django.contrib.auth.models import User
-from django.core.mail import EmailMessage
-
-import mezzanine_agenda.models as ma_models
-from mezzanine.generic.models import AssignedKeyword, Keyword
-
-import eve.models as eve_models
-
-
-class Command(BaseCommand):
-    """Synchronize events from E-vement to mezzanine_agenda"""
-
-
-    option_list = BaseCommand.option_list + (
-          make_option('-m', '--meta_event',
-            dest='meta_event',
-            help='define eve meta_event'),
-          )
-
-    default_user = User.objects.get(username='admin')
-
-    def cleanup(self):
-        # for event in ma_models.Event.objects.all():
-        #     event.delete()
-        # for location in ma_models.EventLocation.objects.all():
-        #     location.delete()
-        for event_price in ma_models.EventPrice.objects.all():
-            event_price.delete()
-
-    def handle(self, *args, **kwargs):
-        # self.cleanup()
-        meta_event_name = kwargs.get('meta_event')
-        meta_trans_all = eve_models.MetaEventTranslation.objects.all()
-        for meta_trans in meta_trans_all:
-            if meta_trans.name == meta_event_name:
-                break
-        eve_events = eve_models.Event.objects.filter(meta_event=meta_trans.id)
-        for eve_event in eve_events:
-            event_trans = eve_models.EventTranslation.objects.filter(id=eve_event, lang='fr')[0]
-            manifestations = eve_event.manifestations.all().order_by('happens_at')
-            first = True
-            for manifestation in manifestations:
-                events = ma_models.Event.objects.filter(external_id=manifestation.id)
-                if not events:
-                    event = ma_models.Event(external_id=manifestation.id)
-                else:
-                    event = events[0]
-                event.start = manifestation.happens_at
-                event.end = manifestation.happens_at + timedelta(seconds=manifestation.duration)
-                event.title = event_trans.name
-                event.user = self.default_user
-
-                locations = ma_models.EventLocation.objects.filter(title=manifestation.location.name)
-                if locations:
-                    location = locations[0]
-                else:
-                    location = ma_models.EventLocation(title=manifestation.location.name)
-                address = '\n'.join([manifestation.location.address, manifestation.location.postalcode + ' ' + manifestation.location.city])
-                location.address = address
-                location.external_id = manifestation.id
-                location.clean()
-                location.save()
-                event.location = location
-                event.save()
-                keyword, _ = Keyword.objects.get_or_create(title=eve_event.event_category.name)
-                event.keywords.add(AssignedKeyword(keyword=keyword), bulk=False)
-
-                eve_prices = eve_models.PriceManifestation.objects.filter(manifestation=manifestation)
-                for price in eve_prices:
-                    event_price, c = ma_models.EventPrice.objects.get_or_create(value=float(price.value))
-                    if event:
-                        if not event_price in event.prices.all():
-                            event.prices.add(event_price)
-
-                if not first:
-                    event.parent = parent
-                else:
-                    parent = event
-                    first = False
-
-                event.save()
diff --git a/app/organization/festival/management/commands/wait-for-db.py b/app/organization/festival/management/commands/wait-for-db.py
deleted file mode 100644 (file)
index e2bacf0..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-import os, time
-
-from optparse import make_option
-from django.conf import settings
-from django.core.management.base import BaseCommand, CommandError
-from django.db import connections
-
-
-class Command(BaseCommand):
-    help = "wait for default DB connection"
-
-    db_name = 'default'
-    N = 20
-
-    def handle(self, *args, **options):
-        i = 0
-        connected = False
-        db_conn = connections[self.db_name]
-        while not connected:
-            try:
-                c = db_conn.cursor()
-                connected = True
-            except:
-                print('error connecting to DB...')
-                if i > self.N:
-                    print('...exiting')
-                    raise
-                print('...retrying')
-                i += 1
-                time.sleep(1)
index bab8206e31437d539f5a73058b0014ca7d398b52..f74881be15a170ba63b919ba263036710767037f 100644 (file)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.9.7 on 2016-07-07 09:13
+# Generated by Django 1.9.7 on 2016-07-07 14:14
 from __future__ import unicode_literals
 
 from django.db import migrations, models
@@ -14,9 +14,6 @@ class Migration(migrations.Migration):
 
     dependencies = [
         ('sites', '0002_alter_domain_unique'),
-        ('mezzanine_agenda', '0014_event_brochure'),
-        ('blog', '0003_auto_20151223_1313'),
-        ('pages', '0004_auto_20151223_1313'),
     ]
 
     operations = [
@@ -44,159 +41,25 @@ class Migration(migrations.Migration):
                 ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
                 ('content_fr', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
                 ('content_en', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
+                ('photo', mezzanine.core.fields.FileField(blank=True, max_length=1024, verbose_name='photo')),
+                ('photo_credits', models.CharField(blank=True, max_length=255, null=True, verbose_name='photo credits')),
+                ('photo_alignment', models.CharField(blank=True, choices=[('left', 'left'), ('center', 'center'), ('right', 'right')], default='left', max_length=32, verbose_name='photo alignment')),
+                ('photo_description', models.TextField(blank=True, verbose_name='photo description')),
+                ('photo_card', mezzanine.core.fields.FileField(blank=True, max_length=1024, verbose_name='card photo')),
+                ('photo_card_credits', models.CharField(blank=True, max_length=255, null=True, verbose_name='photo card credits')),
+                ('photo_slider', mezzanine.core.fields.FileField(blank=True, max_length=1024, verbose_name='slider photo')),
+                ('photo_slider_credits', models.CharField(blank=True, max_length=255, null=True, verbose_name='photo slider credits')),
                 ('first_name', models.CharField(blank=True, max_length=255, null=True, verbose_name='first name')),
                 ('last_name', models.CharField(blank=True, max_length=255, null=True, verbose_name='last name')),
                 ('bio', mezzanine.core.fields.RichTextField(blank=True, verbose_name='biography')),
                 ('bio_fr', mezzanine.core.fields.RichTextField(blank=True, null=True, verbose_name='biography')),
                 ('bio_en', mezzanine.core.fields.RichTextField(blank=True, null=True, verbose_name='biography')),
-                ('photo', mezzanine.core.fields.FileField(blank=True, max_length=1024, verbose_name='photo')),
-                ('photo_credits', models.CharField(blank=True, max_length=255, null=True, verbose_name='photo credits')),
-                ('photo_alignment', models.CharField(blank=True, choices=[('left', 'left'), ('right', 'right')], default='left', max_length=32, verbose_name='photo alignment')),
-                ('photo_description', models.TextField(blank=True, verbose_name='photo description')),
-                ('photo_featured', mezzanine.core.fields.FileField(blank=True, max_length=1024, verbose_name='photo featured')),
-                ('photo_featured_credits', models.CharField(blank=True, max_length=255, null=True, verbose_name='photo featured credits')),
-                ('events', models.ManyToManyField(blank=True, related_name='artists', to='mezzanine_agenda.Event', verbose_name='events')),
                 ('site', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
             ],
             options={
-                'verbose_name': 'artist',
                 'ordering': ['last_name'],
+                'verbose_name': 'artist',
             },
-            bases=(models.Model, mezzanine.utils.models.AdminThumbMixin),
-        ),
-        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')),
-                ('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')),
-                ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
-                ('content_fr', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
-                ('content_en', mezzanine.core.fields.RichTextField(null=True, 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')),
-                ('poster_url', models.URLField(blank=True, max_length=1024, verbose_name='poster')),
-                ('artists', models.ManyToManyField(blank=True, related_name='audios', to='organization festival app.Artist', verbose_name='artists')),
-                ('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={
-                'verbose_name': 'audio',
-            },
-        ),
-        migrations.CreateModel(
-            name='Featured',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=512, verbose_name='name')),
-                ('description', models.TextField(blank=True, verbose_name='description')),
-                ('artists', models.ManyToManyField(blank=True, related_name='featured', to='organization festival app.Artist', verbose_name='artists')),
-                ('blogposts', models.ManyToManyField(blank=True, related_name='featured', to='blog.BlogPost', verbose_name='blog posts')),
-                ('events', models.ManyToManyField(blank=True, related_name='featured', to='mezzanine_agenda.Event', verbose_name='events')),
-                ('pages', models.ManyToManyField(blank=True, related_name='featured', to='pages.Page', verbose_name='pages')),
-            ],
-            options={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='Playlist',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=512, verbose_name='title')),
-                ('description', models.TextField(blank=True, verbose_name='description')),
-                ('audios', models.ManyToManyField(blank=True, related_name='playlists', to='organization festival app.Audio', verbose_name='audios')),
-                ('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={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='Video',
-            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')),
-                ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
-                ('content_fr', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
-                ('content_en', mezzanine.core.fields.RichTextField(null=True, 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')),
-                ('poster_url', models.URLField(blank=True, max_length=1024, verbose_name='poster')),
-                ('artists', models.ManyToManyField(blank=True, related_name='videos', to='organization festival app.Artist', verbose_name='artists')),
-            ],
-            options={
-                'verbose_name': 'video',
-            },
-        ),
-        migrations.CreateModel(
-            name='VideoCategory',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('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')),
-                ('site', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
-            ],
-            options={
-                'verbose_name': 'video category',
-            },
-        ),
-        migrations.AddField(
-            model_name='video',
-            name='category',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='videos', to='organization festival app.VideoCategory', verbose_name='category'),
-        ),
-        migrations.AddField(
-            model_name='video',
-            name='event',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='videos', to='mezzanine_agenda.Event', verbose_name='event'),
-        ),
-        migrations.AddField(
-            model_name='video',
-            name='site',
-            field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site'),
-        ),
-        migrations.AddField(
-            model_name='featured',
-            name='playlists',
-            field=models.ManyToManyField(blank=True, related_name='featured', to='organization festival app.Playlist', verbose_name='playlists'),
-        ),
-        migrations.AddField(
-            model_name='featured',
-            name='videos',
-            field=models.ManyToManyField(blank=True, related_name='featured', to='organization festival app.Video', verbose_name='videos'),
+            bases=(mezzanine.utils.models.AdminThumbMixin, models.Model),
         ),
     ]
index 5703b40b387ce877724d5f4d16ceda9b00e26d0a..430ac4bf6eb758044b1bce41f16aa3570573ed38 100644 (file)
@@ -9,56 +9,19 @@ from mezzanine.utils.models import AdminThumbMixin, upload_to
 from mezzanine.blog.models import BlogPost
 from mezzanine.pages.models import Page
 
-from mezzanine_agenda.models import Event
+from organization.core.models import *
+from organization.media.models import *
 
 import requests
 from pyquery import PyQuery as pq
 
 
-ALIGNMENT_CHOICES = (('left', _('left')), ('right', _('right')))
-MEDIA_BASE_URL = getattr(settings, 'MEDIA_BASE_URL', 'http://medias.ircam.fr/embed/media/')
-
-
-
-class BaseNameModel(models.Model):
-    """Base object with name and description"""
-
-    name = models.CharField(_('name'), max_length=512)
-    description = models.TextField(_('description'), blank=True)
-
-    class Meta:
-        abstract = True
-
-    def __unicode__(self):
-        return self.name
-
-class BaseTitleModel(models.Model):
-    """Base object with title and description"""
-
-    title = models.CharField(_('title'), max_length=512)
-    description = models.TextField(_('description'), blank=True)
-
-    class Meta:
-        abstract = True
-
-    def __unicode__(self):
-        return self.title
-
-
-class Artist(Displayable, RichText, AdminThumbMixin):
+class Artist(Displayable, RichText, AdminThumbMixin, Photo):
     """Artist"""
 
     first_name = models.CharField(_('first name'), max_length=255, blank=True, null=True)
     last_name = models.CharField(_('last name'), max_length=255, blank=True, null=True)
     bio = RichTextField(_('biography'), blank=True)
-    photo = FileField(_('photo'), upload_to='images/photos', max_length=1024, blank=True, format="Image")
-    photo_credits = models.CharField(_('photo credits'), max_length=255, blank=True, null=True)
-    photo_alignment = models.CharField(_('photo alignment'), choices=ALIGNMENT_CHOICES, max_length=32, default="left", blank=True)
-    photo_description = models.TextField(_('photo description'), blank=True)
-    photo_featured = FileField(_('photo featured'), upload_to='images/photos', max_length=1024, blank=True, format="Image")
-    photo_featured_credits = models.CharField(_('photo featured credits'), max_length=255, blank=True, null=True)
-    events = models.ManyToManyField(Event, related_name='artists', verbose_name=_('events'), blank=True)
-
     search_fields = ("title", "bio")
 
     class Meta:
@@ -71,142 +34,3 @@ class Artist(Displayable, RichText, AdminThumbMixin):
     @property
     def name(self):
         return self.title
-
-    def get_absolute_url(self):
-        return reverse("festival-artist-detail", kwargs={'slug': self.slug})
-
-    def set_names(self):
-        names = self.title.split(' ')
-        if len(names) == 1:
-            self.first_name = ''
-            self.last_name = names[0]
-        elif len(names) == 2:
-            self.first_name = names[0]
-            self.last_name = names[1]
-        else:
-            self.first_name = names[0]
-            self.last_name = ' '.join(names[1:])
-
-    def clean(self):
-        super(Artist, self).clean()
-        self.set_names()
-
-    def save(self, *args, **kwargs):
-        self.set_names()
-        super(Artist, self).save(*args, **kwargs)
-
-    @property
-    def featured_image(self):
-        if self.photo_featured:
-            return self.photo_featured
-        else:
-            return self.photo
-
-
-class Media(Displayable, RichText):
-    """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)
-    poster_url = models.URLField(_('poster'), max_length=1024, blank=True)
-
-    class Meta:
-        abstract = True
-
-    def __unicode__(self):
-        return self.title
-
-    @property
-    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())
-        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']
-
-
-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)
-    artists = models.ManyToManyField(Artist, verbose_name=_('artists'), related_name='audios', blank=True)
-
-    class Meta:
-        verbose_name = _('audio')
-
-    def get_absolute_url(self):
-        return reverse("festival-video-detail", kwargs={"slug": self.slug})
-
-
-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)
-    category = models.ForeignKey('VideoCategory', related_name='videos', verbose_name=_('category'), blank=True, null=True, on_delete=models.SET_NULL)
-    artists = models.ManyToManyField(Artist, verbose_name=_('artists'), related_name='videos', blank=True)
-
-    class Meta:
-        verbose_name = _('video')
-
-    @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})
-
-
-class Playlist(BaseTitleModel):
-    """(Playlist description)"""
-
-    audios = models.ManyToManyField(Audio, verbose_name=_('audios'), related_name='playlists', blank=True)
-    event = models.ForeignKey(Event, related_name='playlists', verbose_name=_('event'), blank=True, null=True, on_delete=models.SET_NULL)
-
-    def __str__(self):
-        return self.title
-
-
-class Featured(BaseNameModel):
-    """(Featured description)"""
-
-    artists = models.ManyToManyField(Artist, verbose_name=_('artists'), related_name='featured', blank=True)
-    events = models.ManyToManyField(Event, verbose_name=_('events'), related_name='featured', blank=True)
-    videos = models.ManyToManyField(Video, verbose_name=_('videos'), related_name='featured', blank=True)
-    blogposts = models.ManyToManyField(BlogPost, verbose_name=_('blog posts'), related_name='featured', blank=True)
-    pages = models.ManyToManyField(Page, verbose_name=_('pages'), related_name='featured', blank=True)
-    playlists = models.ManyToManyField(Playlist, verbose_name=_('playlists'), related_name='featured', blank=True)
-
-    def __unicode__(self):
-        return self.name
-
-
-class VideoCategory(Slugged):
-    """Video Category"""
-
-    class Meta:
-        verbose_name = _('video category')
-        
-    def count(self):
-        return self.videos.published().count()+1
index 824c59a2f6d71fcd7e197ecb31c0aff710042ecf..5f3c95830887b466d208868fc7a73a1c51e731c9 100644 (file)
@@ -7,6 +7,7 @@ from mezzanine.conf import settings
 from random import shuffle
 
 from organization.festival.models import *
+from organization.magazine.models import *
 
 register = Library()
 
index fabf2bf0554e71f5982c1f9390cf9cd03a49a6fc..b9e4936be8f6bf294c63e98e4b210195f39619cb 100644 (file)
@@ -1,32 +1,8 @@
 from modeltranslation.translator import register, TranslationOptions
 
-from mezzanine_agenda.models import Event, EventLocation
 from organization.festival.models import *
 
-
-@register(Event)
-class EventTranslationOptions(TranslationOptions):
-
-    fields = ('title', 'description', 'content')
-
-@register(EventLocation)
-class EventLocationTranslationOptions(TranslationOptions):
-
-    fields = ('description',)
-
 @register(Artist)
 class ArtistTranslationOptions(TranslationOptions):
 
     fields = ('title', 'description', 'bio', 'content')
-
-
-@register(Video)
-class VideoTranslationOptions(TranslationOptions):
-
-    fields = ('title', 'description', 'content')
-
-
-@register(Audio)
-class AudioTranslationOptions(TranslationOptions):
-
-    fields = ('title', 'description', 'content')
index dbf17f42c9e994e4290105cadfab6043be39e19f..920e5effeb4d1b5e4a08b9576b2067f7f2e25f8d 100644 (file)
@@ -13,7 +13,4 @@ from organization.festival.views import *
 urlpatterns = [
     url(r'^artists/$', ArtistListView.as_view(), name="festival-artist-list"),
     url(r'^artists/detail/(?P<slug>.*)/$', ArtistDetailView.as_view(), name="festival-artist-detail"),
-    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"),
 ]
index 0c55cf80e81473b8adc14c21bee31393e26559cf..beba18131052324b2cf3e7c1075a2893a074f376 100644 (file)
@@ -6,12 +6,7 @@ from django.shortcuts import get_object_or_404
 from organization.festival.models import *
 from mezzanine_agenda.models import EventLocation
 
-
-class SlugMixin(object):
-
-    def get_object(self):
-        objects = self.model.objects.all()
-        return get_object_or_404(objects, slug=self.kwargs['slug'])
+from organization.core.views import *
 
 
 class ArtistListView(ListView):
@@ -36,40 +31,3 @@ class ArtistDetailView(SlugMixin, DetailView):
     def get_context_data(self, **kwargs):
         context = super(ArtistDetailView, self).get_context_data(**kwargs)
         return context
-
-
-class VideoListView(ListView):
-
-    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'] = VideoCategory.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 = VideoCategory.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
index 8c38f3f3dad51e4585f3984282c2a4bec5349c1e..aa592f08f4d01c2573b7558fd042a41b116950d1 100644 (file)
@@ -1,3 +1,3 @@
 from django.contrib import admin
 
-# Register your models here.
+from organization.magazine.models import *
index 53dd878a8167b7d9bcd2911cdcb99be2ff8a8789..412eaf01ebd619b3419f449355cd98106d3f7f38 100644 (file)
@@ -1,9 +1,16 @@
 from __future__ import unicode_literals
+
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse, reverse_lazy
-from mezzanine.blog.models import BlogPost
-from organization.core.models import Named
+
+from mezzanine.blog.models import *
+
+from mezzanine_agenda.models import Event
+
+from organization.magazine.models import *
+from organization.core.models import *
+
 
 class Article(BlogPost):
 
@@ -12,6 +19,7 @@ class Article(BlogPost):
     class Meta:
         verbose_name = _('article')
 
+
 class Category(Named):
     """(Category description)"""
 
index 8c38f3f3dad51e4585f3984282c2a4bec5349c1e..9ea7f15c8bca76216bfd6acd0c0a854c577438cc 100644 (file)
@@ -1,3 +1,39 @@
+from copy import deepcopy
 from django.contrib import admin
+from mezzanine.core.admin import DisplayableAdmin, OwnableAdmin
+from organization.media.models import *
 
-# Register your models here.
+
+class VideoAdmin(admin.ModelAdmin):
+
+    model = Video
+
+
+class VideoAdminDisplayable(DisplayableAdmin):
+
+    fieldsets = deepcopy(VideoAdmin.fieldsets)
+    #filter_horizontal = ['artists']
+
+
+class AudioAdmin(admin.ModelAdmin):
+
+    model = Audio
+
+
+class AudioAdminDisplayable(DisplayableAdmin):
+
+    fieldsets = deepcopy(AudioAdmin.fieldsets)
+    # filter_horizontal = ['artists']
+
+
+class PlaylistAdmin(admin.ModelAdmin):
+
+    model = Playlist
+    list_display = ('__unicode__',)
+    filter_horizontal = ['audios']
+
+
+admin.site.register(Video, VideoAdminDisplayable)
+admin.site.register(Audio, AudioAdminDisplayable)
+admin.site.register(Playlist, PlaylistAdmin)
+admin.site.register(VideoCategory)
diff --git a/app/organization/media/migrations/0001_initial.py b/app/organization/media/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..32ee568
--- /dev/null
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-07-07 14:14
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+import mezzanine.core.fields
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('sites', '0002_alter_domain_unique'),
+    ]
+
+    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')),
+                ('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')),
+                ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
+                ('content_fr', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
+                ('content_en', mezzanine.core.fields.RichTextField(null=True, 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')),
+                ('poster_url', models.URLField(blank=True, max_length=1024, verbose_name='poster')),
+                ('site', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
+            ],
+            options={
+                'verbose_name': 'audio',
+            },
+        ),
+        migrations.CreateModel(
+            name='Playlist',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=512, verbose_name='title')),
+                ('description', models.TextField(blank=True, verbose_name='description')),
+                ('audios', models.ManyToManyField(blank=True, related_name='playlists', to='organization media.Audio', verbose_name='audios')),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='Video',
+            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')),
+                ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
+                ('content_fr', mezzanine.core.fields.RichTextField(null=True, verbose_name='Content')),
+                ('content_en', mezzanine.core.fields.RichTextField(null=True, 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')),
+                ('poster_url', models.URLField(blank=True, max_length=1024, verbose_name='poster')),
+            ],
+            options={
+                'verbose_name': 'video',
+            },
+        ),
+        migrations.CreateModel(
+            name='VideoCategory',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('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')),
+                ('site', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
+            ],
+            options={
+                'verbose_name': 'video category',
+            },
+        ),
+        migrations.AddField(
+            model_name='video',
+            name='category',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='videos', to='organization media.VideoCategory', verbose_name='category'),
+        ),
+        migrations.AddField(
+            model_name='video',
+            name='site',
+            field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.Site'),
+        ),
+    ]
index 3e1ad3978055e6682e6d704e84b808fe3039bb57..c4dfffa052d9c633a8b48fe1109c1175ec383682 100644 (file)
@@ -7,10 +7,15 @@ from mezzanine.core.models import RichText, Displayable, Slugged
 from mezzanine.core.fields import RichTextField, OrderField, FileField
 from mezzanine.utils.models import AdminThumbMixin, upload_to
 
+from mezzanine_agenda.models import Event
+from organization.core.models import *
+
+
 ALIGNMENT_CHOICES = (('left', _('left')), ('center', _('center')), ('right', _('right')))
+MEDIA_BASE_URL = getattr(settings, 'MEDIA_BASE_URL', 'http://medias.ircam.fr/embed/media/')
 
 
-class Photos(models.Model):
+class Photo(models.Model):
     """Photo bundle with credits"""
 
     photo = FileField(_('photo'), upload_to='images/photos', max_length=1024, blank=True, format="Image")
@@ -26,3 +31,98 @@ class Photos(models.Model):
 
     class Meta:
         abstract = True
+
+    @property
+    def card(self):
+        if self.photo_card:
+            return self.photo_card
+        else:
+            return self.photo
+
+
+class Media(Displayable, RichText):
+    """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)
+    poster_url = models.URLField(_('poster'), max_length=1024, blank=True)
+
+    class Meta:
+        abstract = True
+
+    def __unicode__(self):
+        return self.title
+
+    @property
+    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())
+        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']
+
+
+class Audio(Media):
+    """Audio"""
+
+    open_source_mime_type = 'audio/ogg'
+    closed_source_mime_type = 'audio/mp4'
+
+    class Meta:
+        verbose_name = _('audio')
+
+    def get_absolute_url(self):
+        return reverse("festival-video-detail", kwargs={"slug": self.slug})
+
+
+class Video(Media):
+    """Video"""
+
+    open_source_mime_type = 'video/webm'
+    closed_source_mime_type = 'video/mp4'
+    category = models.ForeignKey('VideoCategory', related_name='videos', verbose_name=_('category'), blank=True, null=True, on_delete=models.SET_NULL)
+
+    class Meta:
+        verbose_name = _('video')
+
+    @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})
+
+
+class VideoCategory(Slugged):
+    """Video Category"""
+
+    class Meta:
+        verbose_name = _('video category')
+
+    def count(self):
+        return self.videos.published().count()+1
+
+
+class Playlist(Titled):
+    """(Playlist description)"""
+
+    audios = models.ManyToManyField('Audio', verbose_name=_('audios'), related_name='playlists', blank=True)
+
+    def __str__(self):
+        return self.title
diff --git a/app/organization/media/translation.py b/app/organization/media/translation.py
new file mode 100644 (file)
index 0000000..bd09714
--- /dev/null
@@ -0,0 +1,15 @@
+from modeltranslation.translator import translator, register, TranslationOptions
+
+from organization.media.models import *
+
+
+@register(Video)
+class VideoTranslationOptions(TranslationOptions):
+
+    fields = ('title', 'description', 'content')
+
+
+@register(Audio)
+class AudioTranslationOptions(TranslationOptions):
+
+    fields = ('title', 'description', 'content')
diff --git a/app/organization/media/urls.py b/app/organization/media/urls.py
new file mode 100644 (file)
index 0000000..50ba729
--- /dev/null
@@ -0,0 +1,17 @@
+from __future__ import unicode_literals
+
+from django.conf.urls import patterns, include, url
+from django.conf.urls.i18n import i18n_patterns
+from django.contrib import admin
+
+from mezzanine.core.views import direct_to_template
+from mezzanine.conf import settings
+
+from organization.festival.views import *
+
+
+urlpatterns = [
+    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"),
+]
index 91ea44a218fbd2f408430959283f0419c921093e..933be23de7685302eb14f693a16c591a592defa9 100644 (file)
@@ -1,3 +1,41 @@
 from django.shortcuts import render
 
-# Create your views here.
+from organization.media.models import *
+from organization.core.views import *
+
+
+class VideoListView(ListView):
+
+    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'] = VideoCategory.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 = VideoCategory.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
diff --git a/app/organization/structure/migrations/0002_auto_20160707_1614.py b/app/organization/structure/migrations/0002_auto_20160707_1614.py
new file mode 100644 (file)
index 0000000..07f60e1
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-07-07 14:14
+from __future__ import unicode_literals
+
+from django.db import migrations
+import mezzanine.core.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization structure', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name='Modelname',
+        ),
+        migrations.AlterModelOptions(
+            name='person',
+            options={'ordering': ['last_name'], 'verbose_name': 'person'},
+        ),
+        migrations.AddField(
+            model_name='person',
+            name='bio',
+            field=mezzanine.core.fields.RichTextField(blank=True, verbose_name='biography'),
+        ),
+    ]
index d126734de3471c3c158f5997fc3eccff20cfbc55..139ccfe1fbae1e0bb384e68b411cbced29acd87c 100644 (file)
@@ -21,7 +21,7 @@ from mezzanine.utils.models import AdminThumbMixin, upload_to
 
 from django_countries.fields import CountryField
 
-from organization.media.models import Photos
+from organization.media.models import Photo
 from organization.core.models import Named
 
 # Hack to have these strings translated
@@ -100,7 +100,7 @@ class Team(Named):
         return u"Team"
 
 
-class Person(Displayable, RichText, AdminThumbMixin, Photos):
+class Person(Displayable, RichText, AdminThumbMixin, Photo):
     """(Person description)"""
 
     user = models.ForeignKey(User, verbose_name=_('user'), blank=True, null=True, on_delete=models.SET_NULL)
@@ -110,10 +110,38 @@ class Person(Displayable, RichText, AdminThumbMixin, Photos):
     last_name = models.CharField(_('last name'), max_length=255, blank=True, null=True)
     birthday = models.DateField(_('birthday'), blank=True)
     organization = models.ForeignKey('Organization', verbose_name=_('organization'), blank=True, null=True, on_delete=models.SET_NULL)
+    bio = RichTextField(_('biography'), blank=True)
+
+    class Meta:
+        verbose_name = _('person')
+        ordering = ['last_name',]
 
     def __unicode__(self):
         return ' '.join((self.user.first_name, self.user.last_name))
 
+    # def get_absolute_url(self):
+    #     return reverse("festival-artist-detail", kwargs={'slug': self.slug})
+
+    def set_names(self):
+        names = self.title.split(' ')
+        if len(names) == 1:
+            self.first_name = ''
+            self.last_name = names[0]
+        elif len(names) == 2:
+            self.first_name = names[0]
+            self.last_name = names[1]
+        else:
+            self.first_name = names[0]
+            self.last_name = ' '.join(names[1:])
+
+    def clean(self):
+        super(Person, self).clean()
+        self.set_names()
+
+    def save(self, *args, **kwargs):
+        self.set_names()
+        super(Person, self).save(*args, **kwargs)
+
 
 class Nationality(models.Model):
     """(Nationality description)"""
@@ -172,11 +200,3 @@ class Activity(models.Model):
 
     def __unicode__(self):
         return ' - '.join((self.person, self.role, self.date_begin, self.date_end))
-
-
-class Modelname(models.Model):
-    """( description)"""
-
-
-    def __unicode__(self):
-        return u""
index eaa2f40d1cf3e2d0dca910d69408c1b7d2dc6b2c..c601f7adb1d9d739a4ea46e5d8334526cc5608bd 100644 (file)
@@ -229,6 +229,7 @@ INSTALLED_APPS = [
     "organization.magazine",
     "organization.media",
     "organization.project",
+    "organization.featured",
 ]
 
 
index 05812b252b173998dc76a7d0f0e4b10f26f6e967..880ded65e4f204d6fb544f7303d06b249f7c337d 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "agenda/event_detail.html" %}
-{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags festival_tags %}
+{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags featured_tags %}
 
 {% block event_detail_postedby %}
 {% endblock %}
index 4eb5e14a1e8870e8719d2a19f300464cf0510fb0..e6df9efe32904a2a62844d1307c7a1b10b227d1c 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "agenda/event_list.html" %}
-{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags festival_tags %}
+{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags featured_tags %}
 
 {% block meta_title %}{{ event.meta_title }}{% endblock %}
 
index 769f91d4670ff17bffa53a61a17e35f7833735e3..61f0befd6adae544c78689765f6939639f613a1d 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "agenda/event_detail.html" %}
-{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags festival_tags %}
+{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n future disqus_tags event_tags featured_tags %}
 
 {% block title %}
     {{ title }}
index adfbb11c9d152eeeba96de782c603d73fa301901..c836e03d862b6ec4276fbf3315925f7812266cc6 100644 (file)
@@ -1,4 +1,4 @@
-{% load i18n mezzanine_tags event_tags festival_tags %}
+{% load i18n mezzanine_tags event_tags featured_tags %}
 <div class="event__meta">
     <div class="event__meta__inner">
         {{ event.start }}
index adfda78815518107c1f63c1229fc9c32dabca5d7..a748baff10cb1000e407948f349ebf4281f3006c 100644 (file)
@@ -1,4 +1,4 @@
-{% load i18n mezzanine_tags event_tags festival_tags %}
+{% load i18n mezzanine_tags event_tags featured_tags %}
 <div class="event__meta--alt">
     <div class="event__meta__inner">
         <div class="split-container">
index 1cf860e876f8e41a10f68094c3a88e41e357ca94..7b35715f7e39d0445bb775358d915c613fe8892d 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype html>
 <html lang="{{ LANGUAGE_CODE }}"{% if LANGUAGE_BIDI %} dir="rtl"{% endif %}>
-{% load i18n pages_tags mezzanine_tags staticfiles keyword_tags event_tags festival_tags %}
+{% load i18n pages_tags mezzanine_tags staticfiles keyword_tags event_tags featured_tags %}
 {% get_language_info_list for LANGUAGES as languages %}
 <head>
     <meta http-equiv="Content-type" content="text/html; charset=utf-8">
index d052deee6e2350fde6dd8466e51273773bb00dfb..9cb3f5368f4f82dd70427990a860de7e565e7ef2 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "blog/blog_post_list.html" %}
-{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n disqus_tags festival_tags %}
+{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n disqus_tags featured_tags %}
 
 {% block meta_title %}{{ blog_post.meta_title }}{% endblock %}
 
index 6c6a887af5fc8eacde91b9bd9bd7b4f6e3d555bc..fdfca906732df6c0f9140043a37b62a9d264eb78 100644 (file)
@@ -1,4 +1,4 @@
-{% load i18n event_tags festival_tags mezzanine_tags %}
+{% load i18n event_tags featured_tags mezzanine_tags %}
 <div class="hero__slider">
     <ul id="lightSlider">
         {% featured_events as events %}
index a315a7ce53e812658a97eec872c35bf0b5eca8ae..b54288be888adbbf831cdbbb57a94ee3529d8ae1 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "base.html" %}
-{% load i18n festival_tags %}
+{% load i18n featured_tags %}
 
 {% block meta_title %}{% trans "Home" %}{% endblock %}
 
index efa355ff91664f3f021e50bbc219c17d33f623a2..f36fcf9e9f6d864d1fc67c8c663ab58324dc743a 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "base.html" %}
-{% load i18n mezzanine_tags keyword_tags festival_tags %}
+{% load i18n mezzanine_tags keyword_tags featured_tags %}
 
 {% block meta_title %}{{ page.meta_title }}{% endblock %}
 
index 141c6013a30fc677c690b9b7e96c7c4922635762..b56657f4f7f79b393a67d9f4c87a7baf8a1255e0 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "base.html" %}
-{% load i18n mezzanine_tags keyword_tags festival_tags %}
+{% load i18n mezzanine_tags keyword_tags featured_tags %}
 
 {% block meta_title %}{{ page.meta_title }}{% endblock %}
 
index 0d2f875f6491224d8bb0f2026fe1531304497bc2..f6f43a6e646dfd1c2e451cc9b11c6a6d1af928c8 100644 (file)
@@ -1,5 +1,5 @@
 {% extends "base.html" %}
-{% load i18n festival_tags %}
+{% load i18n featured_tags %}
 
 {% block meta_title %}{% trans "Styles" %}{% endblock %}
 
index 5e1087c230beb25e758e4afacea51065e8afdb38..95ca5cd91def2f6a115c4761bdb96edbb1715e77 100644 (file)
@@ -1,6 +1,6 @@
 {% extends "base.html" %}
 {% load i18n %}
-{% load mezzanine_tags keyword_tags festival_tags %}
+{% load mezzanine_tags keyword_tags featured_tags %}
 
 {% block title %}
 {{ artist.name }}
index dcb45e660eb50b0fa19852a150c8e6a1af251cd3..f951aa2a69886f29134d4d76e012cf1e86023d21 100644 (file)
@@ -1,6 +1,6 @@
 {% extends "base.html" %}
 {% load i18n %}
-{% load mezzanine_tags keyword_tags festival_tags %}
+{% load mezzanine_tags keyword_tags featured_tags %}
 
 {% block title %}
  {% trans "Videos" %}
diff --git a/doc/__init__.py b/doc/__init__.py
new file mode 100644 (file)
index 0000000..e69de29