From f73016a8f270d2db4f36b5463b663060f5009fc7 Mon Sep 17 00:00:00 2001 From: Guillaume Pellerin Date: Thu, 25 Feb 2016 13:45:08 +0100 Subject: [PATCH] use Displayable for most of models, update settings, use runserver for now, missing migrations --- app/deploy/start_app.sh | 14 ++- app/festival/admin.py | 65 ++++++++++++- app/festival/migrations/0001_initial.py | 80 --------------- .../migrations/0002_auto_20160201_2339.py | 24 ----- .../migrations/0003_artist_content.py | 21 ---- .../migrations/0004_auto_20160202_0002.py | 24 ----- .../migrations/0005_auto_20160202_0006.py | 24 ----- app/festival/migrations/__init__.py | 0 app/festival/models.py | 97 ++++++++++++++----- app/sandbox/local_settings.py | 13 ++- app/sandbox/settings.py | 9 ++ app/sandbox/urls.py | 3 +- app/templates/base.html | 8 +- app/wait.py | 1 - docker-compose.yml | 4 +- requirements-dev.txt | 2 - requirements.txt | 6 +- 17 files changed, 173 insertions(+), 222 deletions(-) delete mode 100644 app/festival/migrations/0001_initial.py delete mode 100644 app/festival/migrations/0002_auto_20160201_2339.py delete mode 100644 app/festival/migrations/0003_artist_content.py delete mode 100644 app/festival/migrations/0004_auto_20160202_0002.py delete mode 100644 app/festival/migrations/0005_auto_20160202_0006.py delete mode 100644 app/festival/migrations/__init__.py diff --git a/app/deploy/start_app.sh b/app/deploy/start_app.sh index 43f7e9c0..e94244d6 100644 --- a/app/deploy/start_app.sh +++ b/app/deploy/start_app.sh @@ -6,6 +6,7 @@ manage=$app'/manage.py' wsgi=$app'/wsgi.py' static='/srv/static/' media='/srv/media/' +src='/srv/src/' # uwsgi params port=8000 @@ -16,7 +17,7 @@ uid='www-data' gid='www-data' # Staging -pip install psycopg2 +# pip install psycopg2 chown -R $uid:$gid $media @@ -24,7 +25,7 @@ chown -R $uid:$gid $media sh $app/deploy/wait.sh # waiting for available database -python $app/wait.py +# python $app/wait.py # python $manage wait-for-db-connection # django init @@ -35,10 +36,15 @@ python $manage create-admin-user # static files auto update watchmedo shell-command --patterns="*.js;*.css" --recursive \ - --command='python '$manage' collectstatic --noinput' $static & + --command='python '$manage' collectstatic --noinput' $src & # app start -uwsgi --socket :$port --wsgi-file $wsgi --chdir $app --master \ +if [ $1 = "--runserver" ] +then + python $manage runserver 0.0.0.0:9000 +else + uwsgi --socket :$port --wsgi-file $wsgi --chdir $app --master \ --processes $processes --threads $threads \ --uid $uid --gid $gid \ --py-autoreload $autoreload +fi diff --git a/app/festival/admin.py b/app/festival/admin.py index 2b6d01cb..1438053e 100644 --- a/app/festival/admin.py +++ b/app/festival/admin.py @@ -1,7 +1,64 @@ +from __future__ import unicode_literals + +from copy import deepcopy + from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ + +from mezzanine_agenda.models import Event, EventLocation +from mezzanine_agenda.admin import * + +from mezzanine.conf import settings +from mezzanine.core.admin import DisplayableAdmin, OwnableAdmin + from festival.models import * -admin.site.register(Event) -admin.site.register(Artist) -admin.site.register(Location) -admin.site.register(Video) + +class FestivalEventInline(admin.StackedInline): + model = FestivalEvent + extra = 1 + + +class FestivalEventAdmin(EventAdmin): + """ + Admin class for events. + """ + + inlines = [FestivalEventInline, ] + + +class ArtistAdmin(admin.ModelAdmin): + + model = Artist + + +class VideoAdmin(admin.ModelAdmin): + + model = Video + + +class VideoAdminDisplayable(DisplayableAdmin): + + fieldsets = deepcopy(VideoAdmin.fieldsets) + + +class ArtistAdminDisplayable(DisplayableAdmin): + """ + Admin class for artists. + """ + + fieldsets = deepcopy(ArtistAdmin.fieldsets) + + + def save_form(self, request, form, change): + """ + Super class ordering is important here - user must get saved first. + """ + return DisplayableAdmin.save_form(self, request, form, change) + + +admin.site.unregister(Event) +admin.site.register(Event, FestivalEventAdmin) + +admin.site.register(Artist, ArtistAdminDisplayable) +admin.site.register(Video, VideoAdminDisplayable) diff --git a/app/festival/migrations/0001_initial.py b/app/festival/migrations/0001_initial.py deleted file mode 100644 index dc398e81..00000000 --- a/app/festival/migrations/0001_initial.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('sites', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Artist', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=255, verbose_name='name')), - ('photo', models.ImageField(upload_to=b'photos/%Y/%m/%d', max_length=1024, verbose_name='photo')), - ], - ), - migrations.CreateModel( - name='Event', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)), - ('title', models.CharField(max_length=500, verbose_name='Title')), - ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)), - ('_meta_title', models.CharField(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', blank=True)), - ('description', models.TextField(verbose_name='Description', blank=True)), - ('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(null=True, editable=False)), - ('updated', models.DateTimeField(null=True, editable=False)), - ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])), - ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True)), - ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)), - ('short_url', models.URLField(null=True, blank=True)), - ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')), - ('event_id', models.IntegerField()), - ('artists', models.ManyToManyField(related_name='events', null=True, verbose_name='events', to='festival.Artist', blank=True)), - ('site', models.ForeignKey(editable=False, to='sites.Site')), - ], - options={ - 'db_table': 'event', - 'verbose_name': 'event', - }, - ), - migrations.CreateModel( - name='Location', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('location_id', models.IntegerField()), - ], - ), - migrations.CreateModel( - name='Video', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)), - ('title', models.CharField(max_length=500, verbose_name='Title')), - ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)), - ('_meta_title', models.CharField(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', blank=True)), - ('description', models.TextField(verbose_name='Description', blank=True)), - ('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(null=True, editable=False)), - ('updated', models.DateTimeField(null=True, editable=False)), - ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])), - ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True)), - ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)), - ('short_url', models.URLField(null=True, blank=True)), - ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')), - ('media_id', models.IntegerField(verbose_name='media ID')), - ('artists', models.ManyToManyField(related_name='videos', null=True, verbose_name='artists', to='festival.Artist', blank=True)), - ('site', models.ForeignKey(editable=False, to='sites.Site')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/app/festival/migrations/0002_auto_20160201_2339.py b/app/festival/migrations/0002_auto_20160201_2339.py deleted file mode 100644 index 95250449..00000000 --- a/app/festival/migrations/0002_auto_20160201_2339.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('festival', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='event', - name='artists', - field=models.ManyToManyField(related_name='events', verbose_name='events', to='festival.Artist', blank=True), - ), - migrations.AlterField( - model_name='video', - name='artists', - field=models.ManyToManyField(related_name='videos', verbose_name='artists', to='festival.Artist', blank=True), - ), - ] diff --git a/app/festival/migrations/0003_artist_content.py b/app/festival/migrations/0003_artist_content.py deleted file mode 100644 index 18d6d86c..00000000 --- a/app/festival/migrations/0003_artist_content.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import mezzanine.core.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('festival', '0002_auto_20160201_2339'), - ] - - operations = [ - migrations.AddField( - model_name='artist', - name='content', - field=mezzanine.core.fields.RichTextField(default='', verbose_name='Content'), - preserve_default=False, - ), - ] diff --git a/app/festival/migrations/0004_auto_20160202_0002.py b/app/festival/migrations/0004_auto_20160202_0002.py deleted file mode 100644 index f72243ea..00000000 --- a/app/festival/migrations/0004_auto_20160202_0002.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import mezzanine.core.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('festival', '0003_artist_content'), - ] - - operations = [ - migrations.RemoveField( - model_name='artist', - name='content', - ), - migrations.AddField( - model_name='artist', - name='bio', - field=mezzanine.core.fields.RichTextField(null=True, verbose_name='bio', blank=True), - ), - ] diff --git a/app/festival/migrations/0005_auto_20160202_0006.py b/app/festival/migrations/0005_auto_20160202_0006.py deleted file mode 100644 index 042cfb63..00000000 --- a/app/festival/migrations/0005_auto_20160202_0006.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('festival', '0004_auto_20160202_0002'), - ] - - operations = [ - migrations.AddField( - model_name='artist', - name='photo_credits', - field=models.CharField(max_length=255, null=True, verbose_name='photo credits', blank=True), - ), - migrations.AlterField( - model_name='event', - name='artists', - field=models.ManyToManyField(related_name='events', verbose_name='artists', to='festival.Artist', blank=True), - ), - ] diff --git a/app/festival/migrations/__init__.py b/app/festival/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/app/festival/models.py b/app/festival/models.py index 54fd0a65..0324bc23 100644 --- a/app/festival/models.py +++ b/app/festival/models.py @@ -2,62 +2,109 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from mezzanine.core.models import RichText, Displayable -from mezzanine.core.fields import RichTextField, OrderField +from mezzanine.core.fields import RichTextField, OrderField, FileField +from mezzanine.utils.models import AdminThumbMixin, upload_to -import eve.models +from mezzanine_agenda.models import Event + +# import eve.models from .related import SpanningForeignKey +app_label = 'festival' + class MetaCore: app_label = 'festival' -class Event(Displayable): - """(Event description)""" +class BaseNameModel(models.Model): + """Base object with name and description""" - event_id = models.IntegerField() - # event = SpanningForeignKey(eve.models.EventVersion, related_name='festival_events', verbose_name=_('E-venement event'), blank=True, null=True, default=None) - rich_description = RichText(_('rich description')) - artists = models.ManyToManyField('Artist', related_name='events', verbose_name=_('artists'), blank=True) + name = models.CharField(_('name'), max_length=512) + description = models.TextField(_('description'), blank=True) class Meta(MetaCore): - verbose_name = _('event') - db_table = 'event' + 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(MetaCore): + abstract = True def __unicode__(self): return self.title -class Artist(models.Model): - """(Artist description)""" +class FestivalEvent(models.Model): + """Extensible event metadata""" + + event = models.ForeignKey(Event, related_name='festival_events', verbose_name=_('festival event'), blank=True, null=True, on_delete=models.SET_NULL) + #eve_event = SpanningForeignKey(eve.models.EventVersion, related_name='festival_events', verbose_name=_('E-venement event'), blank=True, null=True, default=None) + eve_event_id = models.IntegerField(_('eve id'), blank=True) + category = models.ForeignKey('EventCategory', related_name='festival_events', verbose_name=_('category'), blank=True, null=True, on_delete=models.SET_NULL) + artists = models.ManyToManyField('Artist', related_name='metaevents', verbose_name=_('artists'), blank=True) + featured = models.BooleanField(_('featured'), default=False) + featured_image = FileField(_('featured image'), upload_to='images/%Y/%m/%d', max_length=1024, blank=True, format="Image") + featured_image_header = FileField(_('featured image header'), upload_to='images/%Y/%m/%d', max_length=1024, blank=True, format="Image") + + class Meta(MetaCore): + verbose_name = _('festival event') + db_table = app_label + '_events' + + def __unicode__(self): + return self.event.title + + +class Artist(Displayable, RichText, AdminThumbMixin): + """Artist""" - name = models.CharField(_('name'), max_length=255) - photo = models.ImageField(_('photo'), upload_to='photos/%Y/%m/%d', max_length=1024) + bio = RichTextField(_('biography'), blank=True) + photo = FileField(_('photo'), upload_to='images/%Y/%m/%d', max_length=1024, blank=True, format="Image") photo_credits = models.CharField(_('photo credits'), max_length=255, blank=True, null=True) - bio = RichTextField(_("bio"), blank=True, null=True) + featured = models.BooleanField(_('featured'), default=False) search_fields = ("name", "bio") def __unicode__(self): return self.name + class Meta(MetaCore): + verbose_name = _('artist') + db_table = app_label + '_artists' -class Video(Displayable): - """(Video description)""" - media_id = models.IntegerField(_('media ID')) - artists = models.ManyToManyField('Artist', related_name='videos', verbose_name=_('artists'), blank=True) +class Video(Displayable, RichText): + """Video""" + + event = models.ForeignKey(Event, related_name='videos', verbose_name=_('event'), blank=True, null=True, on_delete=models.SET_NULL) + media_id = models.IntegerField(_('media id')) def __unicode__(self): - return u"Video" + return -class Location(models.Model): - """(Location description)""" +class EventCategory(BaseNameModel): + """Event Category""" - location_id = models.IntegerField() + class Meta(MetaCore): + verbose_name = _('event category') - def __unicode__(self): - return u"Location" + +class PageCategory(BaseNameModel): + """Page Category""" + + class Meta(MetaCore): + verbose_name = _('page category') + + + +#class Article ? diff --git a/app/sandbox/local_settings.py b/app/sandbox/local_settings.py index 6956d449..e17d945c 100644 --- a/app/sandbox/local_settings.py +++ b/app/sandbox/local_settings.py @@ -1,4 +1,5 @@ import os +from django.utils.translation import ugettext_lazy as _ DEBUG = True @@ -7,7 +8,7 @@ SECRET_KEY = "+3b01&_6_m@@yb4f06$s0zno8vkybh81nbuj_q(xzk+xeih1+s" NEVERCACHE_KEY = "l11tr%#!uc@+%$51(&+%=&z6h9yrw42(jpcj$3_&6evtu6hl%z" # DATABASE_ROUTERS = ['eve.routers.EveRouter', 'festival.routers.FestivalRouter',] -DATABASE_ROUTERS = ['eve.routers.EveRouter',] +# DATABASE_ROUTERS = ['eve.routers.EveRouter',] DATABASES = { 'default': { @@ -72,3 +73,13 @@ SITE_TITLE = 'Manifeste 2016' SITE_TAGLINE = 'Festival 2 juin | 2 juillet 2016' SILENCED_SYSTEM_CHECKS = ['fields.W342',] + +EVENT_USE_FEATURED_IMAGE = True + +ADMIN_MENU_ORDER = ( + (_("Content"), ("pages.Page", "blog.BlogPost", "mezzanine_agenda.Event", + "festival.Artist", "festival.Video", + "generic.ThreadedComment", (_("Media Library"), "fb_browse"),)), + (_("Site"), ("sites.Site", "redirects.Redirect", "conf.Setting")), + (_("Users"), ("auth.User", "auth.Group",)), +) diff --git a/app/sandbox/settings.py b/app/sandbox/settings.py index 2462c6e0..8055a67e 100644 --- a/app/sandbox/settings.py +++ b/app/sandbox/settings.py @@ -124,6 +124,8 @@ FILE_UPLOAD_PERMISSIONS = 0o644 # MAX_UPLOAD_SIZE = 429916160 +EVENT_SLUG = 'events' + ############# # DATABASES # ############# @@ -195,6 +197,7 @@ TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, "templates"),) ################ INSTALLED_APPS = [ + "modeltranslation", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -217,6 +220,7 @@ INSTALLED_APPS = [ # "eve", "festival", "meta", + 'mezzanine_agenda', ] # Add Migration Module path see : https://github.com/stephenmcd/mezzanine/blob/master/docs/model-customization.rst#field-injection-caveats @@ -226,8 +230,13 @@ MIGRATION_MODULES = { "galleries": "migrations.galleries", "pages": "migrations.pages", "conf": "migrations.conf", + "mezzanine_agenda": "migrations.mezzanine_agenda", } +MODELTRANSLATION_TRANSLATION_FILES = ( + 'translations', +) + # List of processors used by RequestContext to populate the context. # Each one should be a callable that takes the request object as its # only parameter and returns a dictionary to add to the context. diff --git a/app/sandbox/urls.py b/app/sandbox/urls.py index bbf5af81..a5836b71 100644 --- a/app/sandbox/urls.py +++ b/app/sandbox/urls.py @@ -25,7 +25,8 @@ if settings.USE_MODELTRANSLATION: ) urlpatterns += patterns('', - (r'^festival/', include('festival.urls')), + url(r'^festival/', include('festival.urls')), + url("^%s/" % settings.EVENT_SLUG, include("mezzanine_agenda.urls")), # We don't want to presume how your homepage works, so here are a # few patterns you can use to set it up. diff --git a/app/templates/base.html b/app/templates/base.html index 9d3d705b..0f3bb280 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -93,13 +93,7 @@
-
- {% block left_panel %} -
{% page_menu "pages/menus/tree.html" %}
- {% endblock %} -
- -
+
{% block main %}{% endblock %}
diff --git a/app/wait.py b/app/wait.py index 451e5b87..877edbd3 100644 --- a/app/wait.py +++ b/app/wait.py @@ -13,4 +13,3 @@ while not up: except: print 'waiting...' time.sleep(10) - call_command('syncdb', interactive=False) diff --git a/docker-compose.yml b/docker-compose.yml index 0cf322b2..8d34662c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,7 +64,9 @@ db: app: build: . - command: /bin/sh deploy/start_app.sh + command: /bin/sh deploy/start_app.sh --runserver + ports: + - "9000:9000" volumes: - ./app/:/srv/app volumes_from: diff --git a/requirements-dev.txt b/requirements-dev.txt index 5e6ac043..e69de29b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +0,0 @@ -mezzanine-agenda -mezzanine_people diff --git a/requirements.txt b/requirements.txt index 3dd47911..8e5ca2de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ ---index-url https://pypi.python.org/simple/ - setuptools uwsgi watchdog MySQL-python==1.2.5 -Django==1.8.7 +Django==1.8.9 + mezzanine==4.0.1 django-modeltranslation django-meta psycopg2 +mezzanine-agenda -- 2.39.5