From: Emilie Date: Fri, 4 Nov 2016 17:24:28 +0000 (+0100) Subject: Event : add related content X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=7c913470dc4722d0390a5c3f5a6067d3d44f1528;p=mezzo.git Event : add related content --- diff --git a/app/organization/agenda/admin.py b/app/organization/agenda/admin.py index f51d4eaf..aa86bf51 100644 --- a/app/organization/agenda/admin.py +++ b/app/organization/agenda/admin.py @@ -4,17 +4,16 @@ from copy import deepcopy from django.contrib import admin from django.utils.translation import ugettext_lazy as _ - +from modeltranslation.admin import TranslationTabularInline from mezzanine.core.admin import * from mezzanine.pages.admin import PageAdmin from mezzanine.conf import settings from mezzanine.core.admin import DisplayableAdmin, OwnableAdmin - from mezzanine_agenda.models import Event, EventCategory from mezzanine_agenda.admin import * - from organization.core.models import * from organization.agenda.models import * +from organization.agenda.forms import * class EventBlockInline(StackedDynamicInlineAdmin): @@ -57,6 +56,21 @@ class EventPeriodInline(TabularDynamicInlineAdmin): model = EventPeriod +class EventRelatedTitleAdmin(TranslationTabularInline): + + model = EventRelatedTitle + + +class DynamicContentEventInline(TabularDynamicInlineAdmin): + + model = DynamicContentEvent + form = DynamicContentEventForm + + class Media: + js = ( + static("mezzanine/js/admin/dynamic_inline.js"), + ) + class CustomEventAdmin(EventAdmin): """ Admin class for events. @@ -69,7 +83,8 @@ class CustomEventAdmin(EventAdmin): list_display.insert(0, "admin_thumb") list_filter = deepcopy(DisplayableAdmin.list_filter) + ("location", "category") inlines = [EventPeriodInline, EventBlockInline, EventImageInline, EventDepartmentInline, - EventPersonInline, EventLinkInline, EventPlaylistInline, EventTrainingInline] + EventPersonInline, EventLinkInline, EventPlaylistInline, EventTrainingInline, + EventRelatedTitleAdmin, DynamicContentEventInline] def save_form(self, request, form, change): """ diff --git a/app/organization/agenda/forms.py b/app/organization/agenda/forms.py new file mode 100644 index 00000000..acb87d20 --- /dev/null +++ b/app/organization/agenda/forms.py @@ -0,0 +1,33 @@ +from dal import autocomplete + +import dal_queryset_sequence +import dal_select2_queryset_sequence + +from django import forms +from django.forms.widgets import HiddenInput +from django.forms import ModelForm +from mezzanine.core.models import Orderable +from organization.magazine.models import Article, Topic, Brief +from organization.pages.models import CustomPage +from organization.agenda.models import Event, DynamicContentEvent +from organization.media.models import Playlist +from organization.network.models import TeamPage +from organization.projects.models import Project + + +class DynamicContentEventForm(autocomplete.FutureModelForm): + + content_object = dal_queryset_sequence.fields.QuerySetSequenceModelField( + queryset=autocomplete.QuerySetSequence( + Article.objects.all(), + CustomPage.objects.all(), + TeamPage.objects.all(), + Project.objects.all() + ), + required=False, + widget=dal_select2_queryset_sequence.widgets.QuerySetSequenceSelect2('dynamic-content-event'), + ) + + class Meta: + model = DynamicContentEvent + fields = ('content_object',) diff --git a/app/organization/agenda/migrations/0016_dynamiccontentevent.py b/app/organization/agenda/migrations/0016_dynamiccontentevent.py new file mode 100644 index 00000000..2dc36a3a --- /dev/null +++ b/app/organization/agenda/migrations/0016_dynamiccontentevent.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.10 on 2016-11-04 17:01 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import mezzanine.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('mezzanine_agenda', '0015_auto_20161021_1937'), + ('organization-agenda', '0015_auto_20161026_1025'), + ] + + operations = [ + migrations.CreateModel( + name='DynamicContentEvent', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('_order', mezzanine.core.fields.OrderField(null=True, verbose_name='Order')), + ('object_id', models.PositiveIntegerField(editable=False, null=True, verbose_name='related object')), + ('content_type', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type')), + ('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dynamic_content_event', to='mezzanine_agenda.Event', verbose_name='event')), + ], + options={ + 'ordering': ('_order',), + 'verbose_name': 'Dynamic Content Event', + }, + ), + ] diff --git a/app/organization/agenda/migrations/0017_auto_20161104_1812.py b/app/organization/agenda/migrations/0017_auto_20161104_1812.py new file mode 100644 index 00000000..57ee7f58 --- /dev/null +++ b/app/organization/agenda/migrations/0017_auto_20161104_1812.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.10 on 2016-11-04 17:12 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mezzanine_agenda', '0015_auto_20161021_1937'), + ('organization-agenda', '0016_dynamiccontentevent'), + ] + + operations = [ + migrations.CreateModel( + name='EventRelatedTitle', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, max_length=1024, null=True, verbose_name='title')), + ('event', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='related_title', to='mezzanine_agenda.Event', verbose_name='event')), + ], + options={ + 'verbose_name': 'related title', + }, + ), + migrations.AlterOrderWithRespectTo( + name='eventrelatedtitle', + order_with_respect_to='event', + ), + ] diff --git a/app/organization/agenda/migrations/0018_auto_20161104_1820.py b/app/organization/agenda/migrations/0018_auto_20161104_1820.py new file mode 100644 index 00000000..560b7dc9 --- /dev/null +++ b/app/organization/agenda/migrations/0018_auto_20161104_1820.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.10 on 2016-11-04 17:20 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('organization-agenda', '0017_auto_20161104_1812'), + ] + + operations = [ + migrations.AddField( + model_name='eventrelatedtitle', + name='title_en', + field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='title'), + ), + migrations.AddField( + model_name='eventrelatedtitle', + name='title_fr', + field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='title'), + ), + ] diff --git a/app/organization/agenda/models.py b/app/organization/agenda/models.py index 9a5c02ad..e0029aa4 100644 --- a/app/organization/agenda/models.py +++ b/app/organization/agenda/models.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from future.builtins import str from django.utils.translation import ugettext_lazy as _ - +from mezzanine.core.models import Orderable from mezzanine.conf import settings from mezzanine_agenda.models import * from organization.core.models import * @@ -101,3 +101,20 @@ class EventTraining(models.Model): class Meta: verbose_name = _("training") verbose_name_plural = _("trainings") + + +class EventRelatedTitle(RelatedTitle): + + event = models.OneToOneField(Event, verbose_name=_('event'), related_name='related_title', blank=True, null=True, on_delete=models.SET_NULL) + + class Meta: + verbose_name = _("related title") + order_with_respect_to = "event" + + +class DynamicContentEvent(DynamicContent, Orderable): + + event = models.ForeignKey(Event, verbose_name=_('event'), related_name='dynamic_content_event', blank=True, null=True, on_delete=models.SET_NULL) + + class Meta: + verbose_name = 'Dynamic Content Event' diff --git a/app/organization/agenda/translation.py b/app/organization/agenda/translation.py index ab36ca9f..a8584341 100644 --- a/app/organization/agenda/translation.py +++ b/app/organization/agenda/translation.py @@ -61,3 +61,15 @@ class EventTrainingLevelTranslationOptions(TranslationOptions): class EventPublicTypeTranslationOptions(TranslationOptions): fields = ('name',) + + +@register(EventRelatedTitle) +class EventRelatedTitleTranslationOptions(TranslationOptions): + + fields = ('title',) + + +@register(DynamicContentEvent) +class DynamicContentEventTranslationOptions(TranslationOptions): + + fields = () diff --git a/app/organization/agenda/urls.py b/app/organization/agenda/urls.py index 0ba3f170..a313f9c7 100644 --- a/app/organization/agenda/urls.py +++ b/app/organization/agenda/urls.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import django.views.i18n +from django.contrib.auth.decorators import permission_required from django.conf.urls import patterns, include, url from django.conf.urls.i18n import i18n_patterns @@ -14,5 +15,6 @@ from organization.agenda.views import * urlpatterns = [ url("^%s/" % settings.EVENT_SLUG, include("mezzanine_agenda.urls")), url("^%s/confirmation/(?P[0-9]*)$" % settings.EVENT_SLUG, ConfirmationView.as_view(), name="organization-agenda-confirmation"), + url("^dynamic-content-event/$", permission_required('event.can_edit')(DynamicContentEventView.as_view()), name='dynamic-content-event'), ] # diff --git a/app/organization/agenda/views.py b/app/organization/agenda/views.py index aa4341cc..44abc5df 100644 --- a/app/organization/agenda/views.py +++ b/app/organization/agenda/views.py @@ -1,5 +1,12 @@ from django.views.generic.base import TemplateView from mezzanine.conf import settings +from dal import autocomplete +from dal_select2_queryset_sequence.views import Select2QuerySetSequenceView +from organization.network.models import TeamPage +from organization.projects.models import Project +from organization.magazine.models import Article +from organization.pages.models import CustomPage +from mezzanine_agenda.models import Event class ConfirmationView(TemplateView): @@ -9,3 +16,33 @@ class ConfirmationView(TemplateView): context = super(ConfirmationView, self).get_context_data(**kwargs) context['confirmation_url'] = settings.EVENT_CONFIRMATION_URL % kwargs['transaction_id'] return context + + +class DynamicContentEventView(Select2QuerySetSequenceView): + + def get_queryset(self): + + articles = Article.objects.all() + custompage = CustomPage.objects.all() + events = Event.objects.all() + teampages = TeamPage.objects.all() + projects = Project.objects.all() + + if self.q: + articles = articles.filter(title__icontains=self.q) + custompage = custompage.filter(title__icontains=self.q) + events = events.filter(title__icontains=self.q) + teampages = teampages.filter(title__icontains=self.q) + projects = projects.filter(title__icontains=self.q) + + qs = autocomplete.QuerySetSequence(articles, custompage, events, teampages, projects) + + if self.q: + # This would apply the filter on all the querysets + qs = qs.filter(title__icontains=self.q) + + # This will limit each queryset so that they show an equal number + # of results. + qs = self.mixup_querysets(qs) + + return qs diff --git a/app/templates/agenda/event_detail.html b/app/templates/agenda/event_detail.html index 95c10e05..f6cb62e2 100644 --- a/app/templates/agenda/event_detail.html +++ b/app/templates/agenda/event_detail.html @@ -168,3 +168,9 @@ {% endwith %} {% endblock %} + +{% block page_related_content %} + {% with dynamic_content=event.dynamic_content_event.all object=event %} + {% include "core/inc/related_content.html" %} + {% endwith %} +{% endblock %}