From eb20a38235d601061c367948a00c28c23309130d Mon Sep 17 00:00:00 2001 From: Emilie Date: Fri, 23 Sep 2016 18:53:02 +0200 Subject: [PATCH] Article [WIP]: add related Article and Event | generalizing card template --- app/organization/magazine/admin.py | 20 ++++++-- app/organization/magazine/forms.py | 18 +++++++- .../migrations/0004_dynamiccontentarticle.py | 32 +++++++++++++ .../migrations/0005_auto_20160923_1821.py | 21 +++++++++ app/organization/magazine/models.py | 8 ++++ app/organization/magazine/translation.py | 13 ++++-- app/organization/magazine/urls.py | 1 + app/organization/magazine/views.py | 23 ++++++++++ .../{home => core}/inc/generic_card.html | 46 +++++++++---------- app/templates/home/inc/body.html | 8 ++-- app/templates/home/inc/brief_card.html | 21 --------- .../magazine/article/article_detail.html | 17 +++---- .../magazine/brief/inc/brief_card.html | 21 +++++++++ .../magazine/topic/topic_detail.html | 2 +- 14 files changed, 184 insertions(+), 67 deletions(-) create mode 100644 app/organization/magazine/migrations/0004_dynamiccontentarticle.py create mode 100644 app/organization/magazine/migrations/0005_auto_20160923_1821.py rename app/templates/{home => core}/inc/generic_card.html (51%) delete mode 100644 app/templates/home/inc/brief_card.html create mode 100644 app/templates/magazine/brief/inc/brief_card.html diff --git a/app/organization/magazine/admin.py b/app/organization/magazine/admin.py index 2499e922..1891bc31 100644 --- a/app/organization/magazine/admin.py +++ b/app/organization/magazine/admin.py @@ -3,9 +3,8 @@ from django import forms from copy import deepcopy from mezzanine.core.admin import * from mezzanine.pages.admin import PageAdmin -#from orderable.admin import OrderableTabularInline #OrderableAdmin, -from organization.magazine.models import Article, Brief, Topic, ArticleImage, ArticlePersonListBlockInline -from organization.magazine.forms import BriefForm, ArticlePersonListForm +from organization.magazine.models import * +from organization.magazine.forms import * class ArticleImageInline(TabularDynamicInlineAdmin): @@ -24,12 +23,25 @@ class ArticlePersonAutocompleteInlineAdmin(TabularDynamicInlineAdmin): form = ArticlePersonListForm +class DynamicContentArticleInline(TabularDynamicInlineAdmin): + + model = DynamicContentArticle + form = DynamicContentArticleForm + + class Media: + js = ( + static("mezzanine/js/admin/dynamic_inline.js"), + ) + + class ArticleAdminDisplayable(DisplayableAdmin): fieldsets = deepcopy(ArticleAdmin.fieldsets) exclude = ('related_posts',) filter_horizontal = ['categories', 'related_articles', ] - inlines = [ArticleImageInline, ArticlePersonAutocompleteInlineAdmin] + inlines = [ArticleImageInline, + ArticlePersonAutocompleteInlineAdmin, + DynamicContentArticleInline] class BriefAdmin(admin.ModelAdmin): #OrderableTabularInline diff --git a/app/organization/magazine/forms.py b/app/organization/magazine/forms.py index 1a316d2b..5f5e6392 100644 --- a/app/organization/magazine/forms.py +++ b/app/organization/magazine/forms.py @@ -2,7 +2,7 @@ from dal import autocomplete import dal_queryset_sequence import dal_select2_queryset_sequence from django import forms -from organization.magazine.models import Article, Topic, Brief, ArticlePersonListBlockInline +from organization.magazine.models import * from organization.pages.models import CustomPage from organization.network.models import PersonListBlock from mezzanine_agenda.models import Event @@ -34,3 +34,19 @@ class ArticlePersonListForm(forms.ModelForm): class Meta: model = ArticlePersonListBlockInline fields = ('person_list_block',) + + +class DynamicContentArticleForm(autocomplete.FutureModelForm): + + content_object = dal_queryset_sequence.fields.QuerySetSequenceModelField( + queryset=autocomplete.QuerySetSequence( + Article.objects.all(), + Event.objects.all() + ), + required=False, + widget=dal_select2_queryset_sequence.widgets.QuerySetSequenceSelect2('dynamic-content-article'), + ) + + class Meta: + model = DynamicContentArticle + fields = ('content_object',) diff --git a/app/organization/magazine/migrations/0004_dynamiccontentarticle.py b/app/organization/magazine/migrations/0004_dynamiccontentarticle.py new file mode 100644 index 00000000..c4a42152 --- /dev/null +++ b/app/organization/magazine/migrations/0004_dynamiccontentarticle.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-23 16:03 +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'), + ('organization-magazine', '0003_articlepersonlistblockinline'), + ] + + operations = [ + migrations.CreateModel( + name='DynamicContentArticle', + 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')), + ('article', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='organization-magazine.Article', verbose_name='article')), + ('content_type', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type')), + ], + options={ + 'verbose_name': 'Dynamic Content Article', + 'ordering': ('_order',), + }, + ), + ] diff --git a/app/organization/magazine/migrations/0005_auto_20160923_1821.py b/app/organization/magazine/migrations/0005_auto_20160923_1821.py new file mode 100644 index 00000000..55f18118 --- /dev/null +++ b/app/organization/magazine/migrations/0005_auto_20160923_1821.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-23 16:21 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('organization-magazine', '0004_dynamiccontentarticle'), + ] + + operations = [ + migrations.AlterField( + model_name='dynamiccontentarticle', + name='article', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dynamic_content_articles', to='organization-magazine.Article', verbose_name='article'), + ), + ] diff --git a/app/organization/magazine/models.py b/app/organization/magazine/models.py index 12cf3762..d9276b26 100644 --- a/app/organization/magazine/models.py +++ b/app/organization/magazine/models.py @@ -85,3 +85,11 @@ class ArticlePersonListBlockInline(Titled): def __str__(self): return self.title + + +class DynamicContentArticle(DynamicContent, Orderable): + + article = models.ForeignKey(Article, verbose_name=_('article'), related_name='dynamic_content_articles', blank=True, null=True, on_delete=models.SET_NULL) + + class Meta: + verbose_name = 'Dynamic Content Article' diff --git a/app/organization/magazine/translation.py b/app/organization/magazine/translation.py index c030a31d..4e57c4e0 100644 --- a/app/organization/magazine/translation.py +++ b/app/organization/magazine/translation.py @@ -4,11 +4,8 @@ from modeltranslation.translator import TranslationOptions from mezzanine.core.translation import (TranslatedSlugged, TranslatedDisplayable, TranslatedRichText) -from organization.magazine.models import (Article, - Topic, - Brief, - ArticleImage, - ArticlePersonListBlockInline) +from organization.magazine.models import * + @register(Article) class ArticleTranslationOptions(TranslationOptions): @@ -38,3 +35,9 @@ class ArticleImageTranslationOptions(TranslationOptions): class ArticlePersonListBlockInlineTranslationOptions(TranslationOptions): pass + + +@register(DynamicContentArticle) +class DynamicContentArticleTranslationOptions(TranslationOptions): + + pass diff --git a/app/organization/magazine/urls.py b/app/organization/magazine/urls.py index 4f188b67..13cb0729 100644 --- a/app/organization/magazine/urls.py +++ b/app/organization/magazine/urls.py @@ -16,4 +16,5 @@ urlpatterns = [ url("^article/detail/(?P.*)%s$" % _slash, ArticleDetailView.as_view(), name="magazine-article-detail"), url("^topic/detail/(?P.*)%s$" % _slash, TopicDetailView.as_view(), name='topic-detail'), url("^object-autocomplete/$", ObjectAutocomplete.as_view(), name='object-autocomplete'), + url("^dynamic-content-article/$", DynamicContentArticleView.as_view(), name='dynamic-content-article'), ] diff --git a/app/organization/magazine/views.py b/app/organization/magazine/views.py index 29c2f010..cded9354 100644 --- a/app/organization/magazine/views.py +++ b/app/organization/magazine/views.py @@ -106,3 +106,26 @@ class ObjectAutocomplete(Select2QuerySetSequenceView): qs = self.mixup_querysets(qs) return qs + + +class DynamicContentArticleView(Select2QuerySetSequenceView): + def get_queryset(self): + + articles = Article.objects.all() + events = Event.objects.all() + + if self.q: + articles = articles.filter(title__icontains=self.q) + events = events.filter(title__icontains=self.q) + + qs = autocomplete.QuerySetSequence(articles, events ) + + 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/home/inc/generic_card.html b/app/templates/core/inc/generic_card.html similarity index 51% rename from app/templates/home/inc/generic_card.html rename to app/templates/core/inc/generic_card.html index 9a4f6cb9..3cd99152 100644 --- a/app/templates/home/inc/generic_card.html +++ b/app/templates/core/inc/generic_card.html @@ -1,37 +1,37 @@ {% load i18n pages_tags mezzanine_tags media_tags organization_tags %} - +
- {% with body.content_object.images.all|get_type:'card' as image %} + {% with content.content_object.images.all|get_type:'card' as image %} {% if image %} {% endif %} {% endwith %}
- {% if body.content_type.model == 'article' %} + {% if content.content_type.model == 'article' %}
{% trans 'News' %}
- {% if body.content_object.department %} + {% if content.content_object.department %}
- {{ body.content_object.department.name }} + {{ content.content_object.department.name }}
{% endif %}
- {% elif body.content_type.model == 'event' %} + {% elif content.content_type.model == 'event' %}
- {% if body.content_object.departments.first %} - {% with body.content_object.departments.first as department %} + {% if content.content_object.departments.first %} + {% with content.content_object.departments.first as department %}
{{ department.department.name }}
{% endwith %} {% endif %} - {% if body.content_object.category %} + {% if content.content_object.category %}
- {{ body.content_object.category }} + {{ content.content_object.category }}
{% endif %}
@@ -39,32 +39,32 @@
-

{{ body.content_object.title }}

+

{{ content.content_object.title }}

- {% if body.content_type.model == 'article' %} - {{ body.content_object.publish_date|date:"DATE_FORMAT" }} - {% for category in body.content_object.categories.all %} + {% if content.content_type.model == 'article' %} + {{ content.content_object.publish_date|date:"DATE_FORMAT" }} + {% for category in content.content_object.categories.all %} {% if forloop.first %} | {% endif %} {% if not forloop.first %}, {% endif %} {{ category }} {% endfor %} - {% elif body.content_type.model == 'event' %} - {% if body.content_object.start %} - {% if body.content_object.end %} + {% elif content.content_type.model == 'event' %} + {% if content.content_object.start %} + {% if content.content_object.end %} {% trans "From" %} {% endif %} - {{ body.content_object.start|date:"DATE_FORMAT" }} - {% if body.content_object.end %} - {% trans "to" %} {{ body.content_object.end|date:"DATE_FORMAT" }} + {{ content.content_object.start|date:"DATE_FORMAT" }} + {% if content.content_object.end %} + {% trans "to" %} {{ content.content_object.end|date:"DATE_FORMAT" }} {% endif %} {% endif %} - {% if body.content_object.location %} -
{{ body.content_object.location }} + {% if content.content_object.location %} +
{{ content.content_object.location }} {% endif %} {% endif %}
- {{ body.content_object.description|richtext_filters|safe|truncatechars_html:200 }} + {{ content.content_object.description|richtext_filters|safe|truncatechars_html:200 }}
diff --git a/app/templates/home/inc/body.html b/app/templates/home/inc/body.html index 5bcfdfa4..dc977b14 100644 --- a/app/templates/home/inc/body.html +++ b/app/templates/home/inc/body.html @@ -1,11 +1,11 @@
- {% for body in home.dynamiccontenthomebody_set.all %} + {% for content in home.dynamiccontenthomebody_set.all %}
- {% if body.content_type.model == "brief" %} - {% include "home/inc/brief_card.html" %} + {% if content.content_type.model == "brief" %} + {% include "magazine/brief/inc/brief_card.html" %} {% else %} - {% include "home/inc/generic_card.html" %} + {% include "core/inc/generic_card.html" %} {% endif %}
{% endfor %} diff --git a/app/templates/home/inc/brief_card.html b/app/templates/home/inc/brief_card.html deleted file mode 100644 index e9b66265..00000000 --- a/app/templates/home/inc/brief_card.html +++ /dev/null @@ -1,21 +0,0 @@ -{% load i18n %} - -
- -
- {% trans 'Brief !' %} -
- -

{{ body.content_object.title }}

-
- {{ body.content_object.description|slice:":500" }} -
- {% if body.content_object.external_content %} - {{ body.content_object.text_button }} - {% elif body.content_object.content_object %} - {{ body.content_object.text_button }} - {% else %} - {{ body.content_object.title }} - {% endif %} - -
diff --git a/app/templates/magazine/article/article_detail.html b/app/templates/magazine/article/article_detail.html index 4b7f16e4..8d0941ed 100644 --- a/app/templates/magazine/article/article_detail.html +++ b/app/templates/magazine/article/article_detail.html @@ -86,11 +86,8 @@ {% endfor %} {% endblock %} - {% block page_related_content %} - - {% if article.related_articles.all %} - + {% if article.dynamic_content_articles.all %}
@@ -100,17 +97,21 @@
- {% for article in article.related_articles.all %} + {% for content in article.dynamic_content_articles.all %} + {% if content.content_model == "article" %} +
+ {% include 'magazine/article/includes/article_card.html' %} +
+ {% else %}
- {% include 'magazine/article/includes/article_card.html' %} + {% include "core/inc/generic_card.html" %}
+ {%endif%} {% endfor %}
- {% endif %} - {% endblock %} {% block page_sidebar %} diff --git a/app/templates/magazine/brief/inc/brief_card.html b/app/templates/magazine/brief/inc/brief_card.html new file mode 100644 index 00000000..ce0b038c --- /dev/null +++ b/app/templates/magazine/brief/inc/brief_card.html @@ -0,0 +1,21 @@ +{% load i18n %} + +
+ +
+ {% trans 'Brief !' %} +
+ +

{{content.content_object.title }}

+
+ {{content.content_object.description|slice:":500" }} +
+ {% if content.content_object.external_content %} + {{ content.content_object.text_button }} + {% elif content.content_object.content_object %} + {{ content.content_object.text_button }} + {% else %} + {{ content.content_object.title }} + {% endif %} + +
diff --git a/app/templates/magazine/topic/topic_detail.html b/app/templates/magazine/topic/topic_detail.html index dcd45d06..b9f48504 100644 --- a/app/templates/magazine/topic/topic_detail.html +++ b/app/templates/magazine/topic/topic_detail.html @@ -70,5 +70,5 @@ {% pagination_for articles %} - + {% endblock %} -- 2.39.5