From 67e3fa0128857c1db61962c53f178076c09d68f7 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Sun, 26 Jun 2016 15:33:00 +0200 Subject: [PATCH 1/6] Multisite filters --- HISTORY.rst | 1 + djangocms_blog/cms_plugins.py | 29 +++--- djangocms_blog/liveblog/__init__.py | 1 + djangocms_blog/managers.py | 10 ++- .../migrations/0023_auto_20160626_1539.py | 30 +++++++ djangocms_blog/models.py | 40 ++++++--- .../djangocms_blog/plugins/categories.html | 2 +- tests/base.py | 2 + tests/test_models.py | 59 ++++++++++--- tests/test_plugins.py | 88 ++++++++++++++----- 10 files changed, 199 insertions(+), 63 deletions(-) create mode 100644 djangocms_blog/migrations/0023_auto_20160626_1539.py diff --git a/HISTORY.rst b/HISTORY.rst index 6a4d3f5..c068461 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -10,6 +10,7 @@ History * Dropped support for Django<1.8, django CMS<3.2. * Added liveblog application. +* Refactored plugin filters: by default only current site are now shown. * Added standalone documentation at https://djangocms-blog.readthedocs.io. ****************** diff --git a/djangocms_blog/cms_plugins.py b/djangocms_blog/cms_plugins.py index e7fc28c..96c85b5 100644 --- a/djangocms_blog/cms_plugins.py +++ b/djangocms_blog/cms_plugins.py @@ -5,6 +5,8 @@ import os.path from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool +from django.contrib.sites.shortcuts import get_current_site +from django.db import models from .forms import LatestEntriesForm from .models import AuthorEntriesPlugin, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, Post @@ -36,7 +38,7 @@ class BlogLatestEntriesPlugin(BlogPlugin): def render(self, context, instance, placeholder): context = super(BlogLatestEntriesPlugin, self).render(context, instance, placeholder) - context['posts_list'] = instance.get_posts(context['request']) + context['posts_list'] = instance.get_posts(context['request'], published_only=False) context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') return context @@ -54,7 +56,7 @@ class BlogLatestEntriesPluginCached(BlogPlugin): def render(self, context, instance, placeholder): context = super(BlogLatestEntriesPluginCached, self).render(context, instance, placeholder) - context['posts_list'] = instance.get_posts() + context['posts_list'] = instance.get_posts(context['request']) context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') return context @@ -80,11 +82,8 @@ class BlogTagsPlugin(BlogPlugin): def render(self, context, instance, placeholder): context = super(BlogTagsPlugin, self).render(context, instance, placeholder) - qs = Post._default_manager - qs_post = qs - if instance.app_config: - qs_post = qs_post.namespace(instance.app_config.namespace) - context['tags'] = qs.tag_cloud(queryset=qs_post.published()) + qs = instance.post_queryset(context['request']) + context['tags'] = Post.objects.tag_cloud(queryset=qs.published()) return context @@ -96,10 +95,15 @@ class BlogCategoryPlugin(BlogPlugin): def render(self, context, instance, placeholder): context = super(BlogCategoryPlugin, self).render(context, instance, placeholder) - qs = BlogCategory._default_manager + qs = BlogCategory.objects.language().active_translations() if instance.app_config: qs = qs.namespace(instance.app_config.namespace) - context['categories'] = qs + if instance.current_site: + site = get_current_site(context['request']) + qs = qs.filter( + models.Q(blog_posts__sites__isnull=True) | models.Q(blog_posts__sites=site.pk) + ) + context['categories'] = qs.distinct() return context @@ -111,11 +115,8 @@ class BlogArchivePlugin(BlogPlugin): def render(self, context, instance, placeholder): context = super(BlogArchivePlugin, self).render(context, instance, placeholder) - qs = Post._default_manager - qs_post = qs - if instance.app_config: - qs_post = qs.namespace(instance.app_config.namespace) - context['dates'] = qs.get_months(queryset=qs_post.published()) + qs = instance.post_queryset(context['request']) + context['dates'] = Post.objects.get_months(queryset=qs.published()) return context diff --git a/djangocms_blog/liveblog/__init__.py b/djangocms_blog/liveblog/__init__.py index f3a5710..d6e8ab9 100644 --- a/djangocms_blog/liveblog/__init__.py +++ b/djangocms_blog/liveblog/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, unicode_literals + default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig' diff --git a/djangocms_blog/managers.py b/djangocms_blog/managers.py index 004d383..86c4214 100644 --- a/djangocms_blog/managers.py +++ b/djangocms_blog/managers.py @@ -56,8 +56,10 @@ class TaggedFilterItem(object): queryset = self.tag_list(other_model, queryset) return queryset.values('slug') - def tag_cloud(self, other_model=None, queryset=None, published=True): + def tag_cloud(self, other_model=None, queryset=None, published=True, on_site=False): from taggit.models import TaggedItem + if on_site: + queryset = queryset.on_site() tag_ids = self._taglist(other_model, queryset) kwargs = {} if published: @@ -80,9 +82,11 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset): end_date_field = 'date_published_end' publish_field = 'publish' - def on_site(self): + def on_site(self, site=None): + if not site: + site = Site.objects.get_current() return self.filter(models.Q(sites__isnull=True) | - models.Q(sites=Site.objects.get_current().pk)) + models.Q(sites=site.pk)) def published(self): queryset = self.published_future() diff --git a/djangocms_blog/migrations/0023_auto_20160626_1539.py b/djangocms_blog/migrations/0023_auto_20160626_1539.py new file mode 100644 index 0000000..5748fae --- /dev/null +++ b/djangocms_blog/migrations/0023_auto_20160626_1539.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-06-26 13:39 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_blog', '0022_auto_20160605_2305'), + ] + + operations = [ + migrations.AddField( + model_name='authorentriesplugin', + name='current_site', + field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + ), + migrations.AddField( + model_name='genericblogplugin', + name='current_site', + field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + ), + migrations.AddField( + model_name='latestpostsplugin', + name='current_site', + field=models.BooleanField(default=True, help_text='Select items from the current site only', verbose_name='current site'), + ), + ] diff --git a/djangocms_blog/models.py b/djangocms_blog/models.py index ba72459..2878b09 100644 --- a/djangocms_blog/models.py +++ b/djangocms_blog/models.py @@ -8,6 +8,7 @@ from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableMana from cms.models import CMSPlugin, PlaceholderField from django.conf import settings as dj_settings from django.contrib.auth import get_user_model +from django.contrib.sites.shortcuts import get_current_site from django.core.cache import cache from django.core.urlresolvers import reverse from django.db import models @@ -15,6 +16,7 @@ from django.db.models.signals import post_save, pre_delete from django.dispatch import receiver from django.utils import timezone from django.utils.encoding import force_bytes, force_text, python_2_unicode_compatible +from django.utils.functional import cached_property from django.utils.html import escape, strip_tags from django.utils.text import slugify from django.utils.translation import get_language, ugettext_lazy as _ @@ -76,9 +78,17 @@ class BlogCategory(TranslatableModel): verbose_name = _('blog category') verbose_name_plural = _('blog categories') - @property + @cached_property + def linked_posts(self): + return self.blog_posts.namespace(self.app_config.namespace).published() + + @cached_property def count(self): - return self.blog_posts.namespace(self.app_config.namespace).published().count() + return self.linked_posts.on_site().count() + + @cached_property + def count_all_sites(self): + return self.linked_posts.count() def get_absolute_url(self, lang=None): if not lang: @@ -365,17 +375,23 @@ class BasePostPlugin(CMSPlugin): app_config = AppHookConfigField( BlogConfig, null=True, verbose_name=_('app. config'), blank=True ) + current_site = models.BooleanField( + _('current site'), default=True, help_text=_('Select items from the current site only') + ) class Meta: abstract = True - def post_queryset(self, request=None): + def post_queryset(self, request=None, published_only=True): language = get_language() - posts = Post._default_manager + posts = Post.objects if self.app_config: posts = posts.namespace(self.app_config.namespace) + if self.current_site: + posts = posts.on_site(get_current_site(request)) posts = posts.active_translations(language_code=language) - if not request or not getattr(request, 'toolbar', False) or not request.toolbar.edit_mode: + if (published_only or not request or not getattr(request, 'toolbar', False) or + not request.toolbar.edit_mode): posts = posts.published() return posts.all() @@ -384,14 +400,14 @@ class BasePostPlugin(CMSPlugin): class LatestPostsPlugin(BasePostPlugin): latest_posts = models.IntegerField(_('articles'), default=get_setting('LATEST_POSTS'), help_text=_('The number of latests ' - u'articles to be displayed.')) + 'articles to be displayed.')) tags = TaggableManager(_('filter by tag'), blank=True, help_text=_('Show only the blog articles tagged with chosen tags.'), related_name='djangocms_blog_latest_post') categories = models.ManyToManyField('djangocms_blog.BlogCategory', blank=True, verbose_name=_('filter by category'), help_text=_('Show only the blog articles tagged ' - u'with chosen categories.')) + 'with chosen categories.')) def __str__(self): return force_text(_('%s latest articles by tag') % self.latest_posts) @@ -402,8 +418,8 @@ class LatestPostsPlugin(BasePostPlugin): for category in oldinstance.categories.all(): self.categories.add(category) - def get_posts(self, request): - posts = self.post_queryset(request) + def get_posts(self, request, published_only=True): + posts = self.post_queryset(request, published_only) if self.tags.exists(): posts = posts.filter(tags__in=list(self.tags.all())) if self.categories.exists(): @@ -428,8 +444,8 @@ class AuthorEntriesPlugin(BasePostPlugin): def copy_relations(self, oldinstance): self.authors = oldinstance.authors.all() - def get_posts(self, request): - posts = self.post_queryset(request) + def get_posts(self, request, published_only=True): + posts = self.post_queryset(request, published_only) return posts[:self.latest_posts] def get_authors(self): @@ -439,6 +455,8 @@ class AuthorEntriesPlugin(BasePostPlugin): qs = author.djangocms_blog_post_author if self.app_config: qs = qs.namespace(self.app_config.namespace) + if self.current_site: + qs = qs.on_site() count = qs.filter(publish=True).count() if count: author.count = count diff --git a/djangocms_blog/templates/djangocms_blog/plugins/categories.html b/djangocms_blog/templates/djangocms_blog/plugins/categories.html index a6a2e72..135a67b 100644 --- a/djangocms_blog/templates/djangocms_blog/plugins/categories.html +++ b/djangocms_blog/templates/djangocms_blog/plugins/categories.html @@ -16,4 +16,4 @@ {% endfor %} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/tests/base.py b/tests/base.py index d88ea7b..0b79716 100644 --- a/tests/base.py +++ b/tests/base.py @@ -154,6 +154,8 @@ class BaseTest(BaseTestCase): for post in Post.objects.all(): post.sites.clear() post.tags.clear() + post.categories.clear() + cache.clear() super(BaseTest, self).tearDown() def _get_category(self, data, category=None, lang='en'): diff --git a/tests/test_models.py b/tests/test_models.py index befba6b..9f6d9ec 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -611,7 +611,10 @@ class ModelsTest(BaseTest): # default queryset, published and unpublished posts months = Post.objects.get_months() for data in months: - self.assertEqual(data['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual( + data['date'].date(), + now().replace(year=now().year, month=now().month, day=1).date() + ) self.assertEqual(data['count'], 2) # custom queryset, only published @@ -619,7 +622,10 @@ class ModelsTest(BaseTest): post1.save() months = Post.objects.get_months(Post.objects.published()) for data in months: - self.assertEqual(data['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) + self.assertEqual( + data['date'].date(), + now().replace(year=now().year, month=now().month, day=1).date() + ) self.assertEqual(data['count'], 1) self.assertEqual(len(Post.objects.available()), 1) @@ -706,7 +712,9 @@ class ModelsTest(BaseTest): request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False) request_auth = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=False) request_edit = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=True) - plugin = add_plugin(post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) tag = Tag.objects.get(slug='tag-1') plugin.tags.add(tag) # unauthenticated users get no post @@ -714,24 +722,33 @@ class ModelsTest(BaseTest): # staff users not in edit mode get no post self.assertEqual(len(plugin.get_posts(request_auth)), 0) # staff users in edit mode get the post - self.assertEqual(len(plugin.get_posts(request_edit)), 1) + self.assertEqual(len(plugin.get_posts(request_edit, published_only=False)), 1) post1.publish = True post1.save() self.assertEqual(len(plugin.get_posts(request)), 1) + +class ModelsTest2(BaseTest): + def test_copy_plugin_latest(self): post1 = self._get_post(self._post_data[0]['en']) post2 = self._get_post(self._post_data[1]['en']) tag1 = Tag.objects.create(name='tag 1') tag2 = Tag.objects.create(name='tag 2') - plugin = add_plugin(post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) plugin.tags.add(tag1) plugin.tags.add(tag2) if CMS_30: - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by('tree_id', 'level', 'position')) + plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( + 'tree_id', 'level', 'position' + )) else: - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by('path', 'depth', 'position')) + plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( + 'path', 'depth', 'position' + )) copy_plugins_to(plugins, post2.content) new = downcast_plugins(post2.content.cmsplugin_set.all()) self.assertEqual(set(new[0].tags.all()), set([tag1, tag2])) @@ -741,7 +758,9 @@ class ModelsTest(BaseTest): post1 = self._get_post(self._post_data[0]['en']) post2 = self._get_post(self._post_data[1]['en']) request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False) - plugin = add_plugin(post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 + ) plugin.authors.add(self.user) self.assertEqual(len(plugin.get_posts(request)), 0) self.assertEqual(plugin.get_authors()[0].count, 0) @@ -759,12 +778,18 @@ class ModelsTest(BaseTest): def test_copy_plugin_author(self): post1 = self._get_post(self._post_data[0]['en']) post2 = self._get_post(self._post_data[1]['en']) - plugin = add_plugin(post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 + ) plugin.authors.add(self.user) if CMS_30: - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by('tree_id', 'level', 'position')) + plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( + 'tree_id', 'level', 'position' + )) else: - plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by('path', 'depth', 'position')) + plugins = list(post1.content.cmsplugin_set.filter(language='en').order_by( + 'path', 'depth', 'position' + )) copy_plugins_to(plugins, post2.content) new = downcast_plugins(post2.content.cmsplugin_set.all()) self.assertEqual(set(new[0].authors.all()), set([self.user])) @@ -797,13 +822,19 @@ class ModelsTest(BaseTest): self.assertEqual(force_text(post1.categories.first()), 'category 1') - plugin = add_plugin(post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1 + ) self.assertEqual(force_text(plugin.__str__()), '5 latest articles by author') - plugin = add_plugin(post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) self.assertEqual(force_text(plugin.__str__()), '5 latest articles by tag') - plugin = add_plugin(post1.content, 'BlogArchivePlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + post1.content, 'BlogArchivePlugin', language='en', app_config=self.app_config_1 + ) self.assertEqual(force_text(plugin.__str__()), 'generic blog plugin') diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e433e86..3d94443 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -5,6 +5,7 @@ import os.path import re from cms.api import add_plugin +from django.contrib.sites.models import SITE_CACHE from django.core.urlresolvers import reverse from django.utils.timezone import now from taggit.models import Tag @@ -24,7 +25,9 @@ class PluginTest(BaseTest): posts[0].save() ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) tag = Tag.objects.get(slug='tag-1') plugin.tags.add(tag) @@ -34,7 +37,9 @@ class PluginTest(BaseTest): self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1) except AssertionError: self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-1') > -1) - self.assertTrue(rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1) + self.assertTrue( + rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1 + ) self.assertTrue(rendered.find('

first line

') > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) @@ -45,7 +50,9 @@ class PluginTest(BaseTest): category_2.save() category_2.set_current_language('en') posts[1].categories.add(category_2) - plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1) + plugin = add_plugin( + ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) plugin.categories.add(category_2) context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) @@ -54,7 +61,10 @@ class PluginTest(BaseTest): self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-2') > -1) except AssertionError: self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-2') > -1) - self.assertTrue(rendered.find(reverse('djangocms_blog:posts-category', kwargs={'category': category_2.slug})) > -1) + self.assertTrue( + rendered.find(reverse('djangocms_blog:posts-category', + kwargs={'category': category_2.slug})) > -1 + ) self.assertTrue(rendered.find('

second post first line

') > -1) self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(posts[1].get_absolute_url()) > -1) @@ -77,6 +87,16 @@ class PluginTest(BaseTest): self.assertEqual(casted_categories.tags.count(), 0) self.assertEqual(casted_categories.categories.count(), 1) + posts[1].sites.add(self.site_2) + context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + rendered = plugin.render_plugin(context, ph) + self.assertFalse(rendered.find('

second post first line

') > -1) + + posts[1].sites.remove(self.site_2) + context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + rendered = plugin.render_plugin(context, ph) + self.assertTrue(rendered.find('

second post first line

') > -1) + def test_plugin_tags(self): pages = self.get_pages() posts = self.get_posts() @@ -91,7 +111,9 @@ class PluginTest(BaseTest): context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) rendered = plugin.render_plugin(context, ph) for tag in Tag.objects.all(): - self.assertTrue(rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1) + self.assertTrue(rendered.find( + reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug}) + ) > -1) if tag.slug == 'test-tag': rf = '\s+%s\s+\(\s+%s articles' % (tag.name, 2) else: @@ -99,21 +121,6 @@ class PluginTest(BaseTest): rx = re.compile(rf) self.assertEqual(len(rx.findall(rendered)), 1) - def test_blog_category_plugin(self): - pages = self.get_pages() - posts = self.get_posts() - posts[0].publish = True - posts[0].save() - posts[1].publish = True - posts[1].save() - ph = pages[0].placeholders.get(slot='content') - plugin = add_plugin(ph, 'BlogCategoryPlugin', language='en', app_config=self.app_config_1) - plugin_class = plugin.get_plugin_class_instance() - context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) - context = plugin_class.render(context, plugin, ph) - self.assertTrue(context['categories']) - self.assertEqual(list(context['categories']), [self.category_1]) - def test_blog_archive_plugin(self): pages = self.get_pages() posts = self.get_posts() @@ -199,3 +206,44 @@ class PluginTest2(BaseTest): casted_authors, __ = new[0].get_plugin_instance() self.assertEqual(casted_authors.authors.count(), 3) + + def test_blog_category_plugin(self): + pages = self.get_pages() + posts = self.get_posts() + self.category_1.set_current_language('en') + posts[0].publish = True + posts[0].save() + posts[1].publish = True + posts[1].save() + posts[1].sites.add(self.site_2) + new_category = BlogCategory.objects.create( + name='category 2', app_config=self.app_config_1 + ) + posts[1].categories.add(new_category) + + ph = pages[0].placeholders.get(slot='content') + plugin = add_plugin( + ph, 'BlogCategoryPlugin', language='en', app_config=self.app_config_1 + ) + plugin_class = plugin.get_plugin_class_instance() + context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + context = plugin_class.render(context, plugin, ph) + self.assertTrue(context['categories']) + self.assertEqual(list(context['categories']), [self.category_1]) + + plugin.current_site = False + plugin.save() + context = plugin_class.render(context, plugin, ph) + self.assertEqual(list(context['categories']), [self.category_1, new_category]) + + plugin.current_site = True + plugin.save() + with self.settings(SITE_ID=2): + context = plugin_class.render(context, plugin, ph) + self.assertEqual(list(context['categories']), [self.category_1, new_category]) + + plugin.current_site = False + plugin.save() + with self.settings(SITE_ID=2): + context = plugin_class.render(context, plugin, ph) + self.assertEqual(list(context['categories']), [self.category_1, new_category]) From 8b248e7b0fa96c6e75a21b83e070edd414c06d17 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Sun, 26 Jun 2016 18:11:37 +0200 Subject: [PATCH 2/6] More multisites tweaks --- djangocms_blog/managers.py | 32 ++++++++++++++++++++++---------- djangocms_blog/models.py | 14 ++++++++------ tests/test_models.py | 27 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/djangocms_blog/managers.py b/djangocms_blog/managers.py index 86c4214..f7e6ac9 100644 --- a/djangocms_blog/managers.py +++ b/djangocms_blog/managers.py @@ -88,16 +88,19 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset): return self.filter(models.Q(sites__isnull=True) | models.Q(sites=site.pk)) - def published(self): - queryset = self.published_future() + def published(self, current_site=True): + queryset = self.published_future(current_site) if self.start_date_field: return queryset.filter( **{'%s__lte' % self.start_date_field: now()}) else: return queryset - def published_future(self): - queryset = self.on_site() + def published_future(self, current_site=True): + if current_site: + queryset = self.on_site() + else: + queryset = self if self.end_date_field: qfilter = ( models.Q(**{'%s__gte' % self.end_date_field: now()}) | @@ -106,8 +109,11 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset): queryset = queryset.filter(qfilter) return queryset.filter(**{self.publish_field: True}) - def archived(self): - queryset = self.on_site() + def archived(self, current_site=True): + if current_site: + queryset = self.on_site() + else: + queryset = self if self.end_date_field: qfilter = ( models.Q(**{'%s__lte' % self.end_date_field: now()}) | @@ -116,11 +122,17 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset): queryset = queryset.filter(qfilter) return queryset.filter(**{self.publish_field: True}) - def available(self): - return self.on_site().filter(**{self.publish_field: True}) + def available(self, current_site=True): + if current_site: + return self.on_site().filter(**{self.publish_field: True}) + else: + return self.filter(**{self.publish_field: True}) - def filter_by_language(self, language): - return self.active_translations(language_code=language).on_site() + def filter_by_language(self, language, current_site=True): + if current_site: + return self.active_translations(language_code=language).on_site() + else: + return self.active_translations(language_code=language) class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManager): diff --git a/djangocms_blog/models.py b/djangocms_blog/models.py index 2878b09..91df778 100644 --- a/djangocms_blog/models.py +++ b/djangocms_blog/models.py @@ -80,15 +80,15 @@ class BlogCategory(TranslatableModel): @cached_property def linked_posts(self): - return self.blog_posts.namespace(self.app_config.namespace).published() + return self.blog_posts.namespace(self.app_config.namespace) @cached_property def count(self): - return self.linked_posts.on_site().count() + return self.linked_posts.published().count() @cached_property def count_all_sites(self): - return self.linked_posts.count() + return self.linked_posts.published(current_site=False).count() def get_absolute_url(self, lang=None): if not lang: @@ -392,7 +392,7 @@ class BasePostPlugin(CMSPlugin): posts = posts.active_translations(language_code=language) if (published_only or not request or not getattr(request, 'toolbar', False) or not request.toolbar.edit_mode): - posts = posts.published() + posts = posts.published(current_site=self.current_site) return posts.all() @@ -456,8 +456,10 @@ class AuthorEntriesPlugin(BasePostPlugin): if self.app_config: qs = qs.namespace(self.app_config.namespace) if self.current_site: - qs = qs.on_site() - count = qs.filter(publish=True).count() + qs = qs.published() + else: + qs = qs.published(current_site=False) + count = qs.count() if count: author.count = count return authors diff --git a/tests/test_models.py b/tests/test_models.py index 9f6d9ec..dd25f07 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -438,6 +438,33 @@ class AdminTest(BaseTest): class ModelsTest(BaseTest): + def test_category_attributes(self): + posts = self.get_posts() + posts[0].publish = True + posts[0].save() + posts[1].publish = True + posts[1].save() + posts[1].sites.add(self.site_2) + new_category = BlogCategory.objects.create( + name='category 2', app_config=self.app_config_1 + ) + posts[1].categories.add(new_category) + + with self.settings(SITE_ID=2): + self.assertEqual(new_category.count, 1) + self.assertEqual(self.category_1.count, 2) + self.assertEqual(new_category.count_all_sites, 1) + self.assertEqual(self.category_1.count_all_sites, 2) + + # needed to clear cached properties + new_category = self.reload_model(new_category) + self.category_1 = self.reload_model(self.category_1) + with self.settings(SITE_ID=1): + self.assertEqual(new_category.count, 0) + self.assertEqual(self.category_1.count, 1) + self.assertEqual(new_category.count_all_sites, 1) + self.assertEqual(self.category_1.count_all_sites, 2) + def test_model_attributes(self): self.get_pages() From c1edba9772984de4e299448d17a9c8b7df18c4ca Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Tue, 28 Jun 2016 00:26:38 +0200 Subject: [PATCH 3/6] Add option to exclude empty categories from menu --- djangocms_blog/admin.py | 2 +- djangocms_blog/cms_appconfig.py | 4 +++ djangocms_blog/cms_menus.py | 45 ++++++++++++++++++--------------- tests/test_menu.py | 25 ++++++++++++++++++ 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/djangocms_blog/admin.py b/djangocms_blog/admin.py index 7ea2e7c..b849c2f 100755 --- a/djangocms_blog/admin.py +++ b/djangocms_blog/admin.py @@ -262,7 +262,7 @@ class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin): ('Layout', { 'fields': ( 'config.paginate_by', 'config.url_patterns', 'config.template_prefix', - 'config.menu_structure', + 'config.menu_structure', 'config.menu_empty_categories', ), 'classes': ('collapse',) }), diff --git a/djangocms_blog/cms_appconfig.py b/djangocms_blog/cms_appconfig.py index e7e028d..798cf90 100644 --- a/djangocms_blog/cms_appconfig.py +++ b/djangocms_blog/cms_appconfig.py @@ -66,6 +66,10 @@ class BlogConfigForm(AppDataForm): choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE, help_text=_('Structure of the django CMS menu') ) + menu_empty_categories = forms.BooleanField( + label=_('Show empty categories in menu'), initial=True, required=False, + help_text=_('Show categories with no post attached in the menu') + ) sitemap_changefreq = forms.ChoiceField( label=_('Sitemap changefreq'), required=True, choices=get_setting('SITEMAP_CHANGEFREQ'), diff --git a/djangocms_blog/cms_menus.py b/djangocms_blog/cms_menus.py index 426ac09..2b03fcd 100644 --- a/djangocms_blog/cms_menus.py +++ b/djangocms_blog/cms_menus.py @@ -48,33 +48,16 @@ class BlogCategoryMenu(CMSAttachMenu): if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS): posts_menu = True - if categories_menu: - categories = BlogCategory.objects - if config: - categories = categories.namespace(self.instance.application_namespace) - categories = categories.active_translations(language).distinct() - categories = categories.order_by('parent__id', 'translations__name') - for category in categories: - node = NavigationNode( - category.name, - category.get_absolute_url(), - '{0}-{1}'.format(category.__class__.__name__, category.pk), - ( - '{0}-{1}'.format( - category.__class__.__name__, category.parent.id - ) if category.parent else None - ) - ) - nodes.append(node) - + used_categories = [] if posts_menu: posts = Post.objects if hasattr(self, 'instance') and self.instance: - posts = posts.namespace(self.instance.application_namespace) + posts = posts.namespace(self.instance.application_namespace).on_site() posts = posts.active_translations(language).distinct() for post in posts: post_id = None parent = None + used_categories.extend(post.categories.values_list('pk', flat=True)) if categories_menu: category = post.categories.first() if category: @@ -91,6 +74,28 @@ class BlogCategoryMenu(CMSAttachMenu): ) nodes.append(node) + if categories_menu: + categories = BlogCategory.objects + if config: + categories = categories.namespace(self.instance.application_namespace) + if config and not config.menu_empty_categories: + categories = categories.filter(pk__in=used_categories) + else: + categories = categories.active_translations(language).distinct() + categories = categories.order_by('parent__id', 'translations__name') + for category in categories: + node = NavigationNode( + category.name, + category.get_absolute_url(), + '{0}-{1}'.format(category.__class__.__name__, category.pk), + ( + '{0}-{1}'.format( + category.__class__.__name__, category.parent.id + ) if category.parent else None + ) + ) + nodes.append(node) + return nodes menu_pool.register_menu(BlogCategoryMenu) diff --git a/tests/test_menu.py b/tests/test_menu.py index 5400592..89482eb 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -70,6 +70,8 @@ class MenuTest(BaseTest): posts = self.get_posts() cats_url = {} + cats_with_post_url = {} + cats_without_post_url = {} posts_url = {} languages = ('en', 'it') @@ -77,6 +79,8 @@ class MenuTest(BaseTest): for lang in languages: with smart_override(lang): cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) + cats_with_post_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang) and cat.blog_posts.published().exists()]) + cats_without_post_url[lang] = cats_url[lang].difference(cats_with_post_url[lang]) posts_url[lang] = set([post.get_absolute_url(lang) for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1]) # No item in the menu @@ -127,6 +131,27 @@ class MenuTest(BaseTest): self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) + # Both types in the menu + self.app_config_1.app_data.config.menu_empty_categories = False + self.app_config_1.save() + self.app_config_2.app_data.config.menu_empty_categories = False + self.app_config_2.save() + cache.clear() + for lang in languages: + request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) + with smart_override(lang): + nodes = menu_pool.get_nodes(request) + nodes_url = set([node.url for node in nodes]) + self.assertTrue(cats_with_post_url[lang].issubset(nodes_url)) + self.assertFalse(cats_without_post_url[lang].intersection(nodes_url)) + self.assertTrue(posts_url[lang].issubset(nodes_url)) + # Both types in the menu + self.app_config_1.app_data.config.menu_empty_categories = True + self.app_config_1.save() + self.app_config_2.app_data.config.menu_empty_categories = True + self.app_config_2.save() + cache.clear() + def test_modifier(self): """ Tests if correct category is selected in the menu From 7cdfc0e7c701213b001f47dbd2060266c88d4851 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Tue, 28 Jun 2016 00:31:32 +0200 Subject: [PATCH 4/6] Add docs --- HISTORY.rst | 4 +++- djangocms_blog/cms_appconfig.py | 3 ++- djangocms_blog/settings.py | 1 + docs/settings.rst | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index c068461..3bea080 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -10,7 +10,9 @@ History * Dropped support for Django<1.8, django CMS<3.2. * Added liveblog application. -* Refactored plugin filters: by default only current site are now shown. +* Refactored plugin filters: by default only data for current site are now shown. +* Added global and per site posts count to BlogCategory. +* Added option to hide empty categories from menu. * Added standalone documentation at https://djangocms-blog.readthedocs.io. ****************** diff --git a/djangocms_blog/cms_appconfig.py b/djangocms_blog/cms_appconfig.py index 798cf90..0ac4542 100644 --- a/djangocms_blog/cms_appconfig.py +++ b/djangocms_blog/cms_appconfig.py @@ -67,7 +67,8 @@ class BlogConfigForm(AppDataForm): help_text=_('Structure of the django CMS menu') ) menu_empty_categories = forms.BooleanField( - label=_('Show empty categories in menu'), initial=True, required=False, + label=_('Show empty categories in menu'), initial=get_setting('MENU_EMPTY_CATEGORIES'), + required=False, help_text=_('Show categories with no post attached in the menu') ) sitemap_changefreq = forms.ChoiceField( diff --git a/djangocms_blog/settings.py b/djangocms_blog/settings.py index a1b220c..a58ed8f 100644 --- a/djangocms_blog/settings.py +++ b/djangocms_blog/settings.py @@ -58,6 +58,7 @@ def get_setting(name): settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100 ), 'BLOG_MENU_TYPES': MENU_TYPES, + 'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True), 'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'), 'BLOG_TYPES': meta_settings.OBJECT_TYPES, 'BLOG_FB_TYPE': getattr(settings, 'BLOG_FB_TYPE', 'Article'), diff --git a/docs/settings.rst b/docs/settings.rst index a4f4417..36d658a 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -11,6 +11,8 @@ Global Settings detail; it's a dictionary with ``size``, ``crop`` and ``upscale`` keys; (default: ``{'size': '640x120', 'crop': True,'upscale': False}``) * BLOG_PAGINATION: Number of post per page; (default: ``10``) +* BLOG_MENU_EMPTY_CATEGORIES: Flag to show / hide categories without posts + attached from the menu; (default: ``True``) * BLOG_LATEST_POSTS: Default number of post in the **Latest post** plugin; (default: ``5``) * BLOG_POSTS_LIST_TRUNCWORDS_COUNT: Default number of words shown for @@ -119,6 +121,7 @@ be used as defaults. * Paginate sizePer-Apphook setting for BLOG_PAGINATION; * Template prefix: Alternative directory to load the blog templates from; * Menu structure: Per-Apphook setting for BLOG_MENU_TYPE +* Show empty categories in menu: Per-Apphook setting for BLOG_MENU_EMPTY_CATEGORIES * Sitemap changefreq: Per-Apphook setting for BLOG_SITEMAP_CHANGEFREQ_DEFAULT * Sitemap priority: Per-Apphook setting for BLOG_SITEMAP_PRIORITY_DEFAULT * Object type: Per-Apphook setting for BLOG_TYPE From 096e1d48f7b9766d2d875fe7ace82c1124687b19 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Tue, 28 Jun 2016 08:14:07 +0200 Subject: [PATCH 5/6] More manager tests --- djangocms_blog/managers.py | 28 ++++++++++++------------- tests/test_models.py | 43 +++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/djangocms_blog/managers.py b/djangocms_blog/managers.py index f7e6ac9..8091c6a 100644 --- a/djangocms_blog/managers.py +++ b/djangocms_blog/managers.py @@ -116,8 +116,7 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset): queryset = self if self.end_date_field: qfilter = ( - models.Q(**{'%s__lte' % self.end_date_field: now()}) | - models.Q(**{'%s__isnull' % self.end_date_field: False}) + models.Q(**{'%s__lte' % self.end_date_field: now()}) ) queryset = queryset.filter(qfilter) return queryset.filter(**{self.publish_field: True}) @@ -143,29 +142,30 @@ class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManage def get_queryset(self, *args, **kwargs): return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs) - def published(self): - return self.get_queryset().published() + def published(self, current_site=True): + return self.get_queryset().published(current_site) - def available(self): - return self.get_queryset().available() + def available(self, current_site=True): + return self.get_queryset().available(current_site) - def archived(self): - return self.get_queryset().archived() + def archived(self, current_site=True): + return self.get_queryset().archived(current_site) - def published_future(self): - return self.get_queryset().published_future() + def published_future(self, current_site=True): + return self.get_queryset().published_future(current_site) - def filter_by_language(self, language): - return self.get_queryset().filter_by_language(language) + def filter_by_language(self, language, current_site=True): + return self.get_queryset().filter_by_language(language, current_site) - def get_months(self, queryset=None): + def get_months(self, queryset=None, current_site=True): """ Get months with aggregate count (how much posts is in the month). Results are ordered by date. """ if queryset is None: queryset = self.get_queryset() - queryset = queryset.on_site() + if current_site: + queryset = queryset.on_site() dates_qs = queryset.values_list(queryset.start_date_field, queryset.fallback_date_field) dates = [] for blog_dates in dates_qs: diff --git a/tests/test_models.py b/tests/test_models.py index dd25f07..81e169d 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -655,6 +655,24 @@ class ModelsTest(BaseTest): ) self.assertEqual(data['count'], 1) + # Move post to different site to filter it out + post2.sites.add(self.site_2) + months = Post.objects.get_months() + for data in months: + self.assertEqual( + data['date'].date(), + now().replace(year=now().year, month=now().month, day=1).date() + ) + self.assertEqual(data['count'], 1) + months = Post.objects.get_months(current_site=False) + for data in months: + self.assertEqual( + data['date'].date(), + now().replace(year=now().year, month=now().month, day=1).date() + ) + self.assertEqual(data['count'], 2) + post2.sites.clear() + self.assertEqual(len(Post.objects.available()), 1) # If post is published but publishing date is in the future @@ -665,6 +683,7 @@ class ModelsTest(BaseTest): self.assertEqual(len(Post.objects.published()), 1) self.assertEqual(len(Post.objects.published_future()), 2) self.assertEqual(len(Post.objects.archived()), 0) + self.assertEqual(len(Post.objects.archived(current_site=False)), 0) # If post is published but end publishing date is in the past post2.date_published = now().replace(year=now().year - 2, month=now().month, day=1) @@ -673,10 +692,32 @@ class ModelsTest(BaseTest): self.assertEqual(len(Post.objects.available()), 2) self.assertEqual(len(Post.objects.published()), 1) self.assertEqual(len(Post.objects.archived()), 1) + self.assertEqual(len(Post.objects.archived(current_site=False)), 1) + + # Move post to different site to filter it out + post2.sites.add(self.site_2) + self.assertEqual(len(Post.objects.archived()), 0) + self.assertEqual(len(Post.objects.archived(current_site=False)), 1) + self.assertEqual(len(Post.objects.available()), 1) + self.assertEqual(len(Post.objects.available(current_site=False)), 2) + self.assertEqual(len(Post.objects.published()), 1) + + # publish post + post2.date_published = now() - timedelta(days=1) + post2.date_published_end = now() + timedelta(days=10) + post2.save() + self.assertEqual(len(Post.objects.archived()), 0) + self.assertEqual(len(Post.objects.archived(current_site=False)), 0) + self.assertEqual(len(Post.objects.available()), 1) + self.assertEqual(len(Post.objects.available(current_site=False)), 2) + self.assertEqual(len(Post.objects.published()), 1) + self.assertEqual(len(Post.objects.published(current_site=False)), 2) # counting with language fallback enabled self._get_post(self._post_data[0]['it'], post1, 'it') - self.assertEqual(len(Post.objects.filter_by_language('it')), 2) + self.assertEqual(len(Post.objects.filter_by_language('it')), 1) + self.assertEqual(len(Post.objects.filter_by_language('it', current_site=False)), 2) + post2.sites.clear() # No fallback parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = True From 7d28e08f58059922bb7b819a3e82a8acc06c194b Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Tue, 28 Jun 2016 08:56:53 +0200 Subject: [PATCH 6/6] Enabled cached plugin --- HISTORY.rst | 1 + cms_helper.py | 5 +++++ djangocms_blog/cms_plugins.py | 3 ++- djangocms_blog/settings.py | 2 ++ tests/test_plugins.py | 37 +++++++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 3bea080..47d7dba 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,7 @@ History * Added global and per site posts count to BlogCategory. * Added option to hide empty categories from menu. * Added standalone documentation at https://djangocms-blog.readthedocs.io. +* Enabled cached version of BlogLatestEntriesPlugin. ****************** 0.8.5 (2016-06-26) diff --git a/cms_helper.py b/cms_helper.py index 1643ff7..0d1c2d1 100755 --- a/cms_helper.py +++ b/cms_helper.py @@ -96,6 +96,11 @@ HELPER_SETTINGS = dict( HAYSTACK_CONNECTIONS={ 'default': {} }, + CACHES={ + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + } + } ) try: diff --git a/djangocms_blog/cms_plugins.py b/djangocms_blog/cms_plugins.py index 96c85b5..70bb4b5 100644 --- a/djangocms_blog/cms_plugins.py +++ b/djangocms_blog/cms_plugins.py @@ -47,7 +47,7 @@ class BlogLatestEntriesPluginCached(BlogPlugin): """ Cached plugin which returns the latest published posts """ - name = get_setting('LATEST_ENTRIES_PLUGIN_NAME') + name = get_setting('LATEST_ENTRIES_PLUGIN_NAME_CACHED') model = LatestPostsPlugin form = LatestEntriesForm filter_horizontal = ('categories',) @@ -121,6 +121,7 @@ class BlogArchivePlugin(BlogPlugin): plugin_pool.register_plugin(BlogLatestEntriesPlugin) +plugin_pool.register_plugin(BlogLatestEntriesPluginCached) plugin_pool.register_plugin(BlogAuthorPostsPlugin) plugin_pool.register_plugin(BlogTagsPlugin) plugin_pool.register_plugin(BlogArchivePlugin) diff --git a/djangocms_blog/settings.py b/djangocms_blog/settings.py index a58ed8f..0199182 100644 --- a/djangocms_blog/settings.py +++ b/djangocms_blog/settings.py @@ -114,6 +114,8 @@ def get_setting(name): 'BLOG_PLUGIN_MODULE_NAME': getattr(settings, 'BLOG_PLUGIN_MODULE_NAME', _('Blog')), 'BLOG_LATEST_ENTRIES_PLUGIN_NAME': getattr( settings, 'BLOG_LATEST_ENTRIES_PLUGIN_NAME', _('Latest Blog Articles')), + 'BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED': getattr( + settings, 'BLOG_LATEST_ENTRIES_PLUGIN_NAME_CACHED', _('Latest Blog Articles - Cache')), 'BLOG_AUTHOR_POSTS_PLUGIN_NAME': getattr( settings, 'BLOG_AUTHOR_POSTS_PLUGIN_NAME', _('Author Blog Articles')), 'BLOG_TAGS_PLUGIN_NAME': getattr( diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 3d94443..e926fe4 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -17,6 +17,43 @@ from .base import BaseTest class PluginTest(BaseTest): + def test_plugin_latest_cached(self): + pages = self.get_pages() + posts = self.get_posts() + posts[0].tags.add('tag 1') + posts[0].publish = True + posts[0].save() + ph = pages[0].placeholders.get(slot='content') + + plugin = add_plugin( + ph, 'BlogLatestEntriesPluginCached', language='en', app_config=self.app_config_1 + ) + context = self.get_plugin_context(pages[0], 'en', plugin, edit=True) + rendered = plugin.render_plugin(context, ph) + try: + self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1) + except AssertionError: + self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-1') > -1) + self.assertTrue(rendered.find('

first line

') > -1) + self.assertTrue(rendered.find('
-1) + self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) + + plugin_nocache = add_plugin( + ph, 'BlogLatestEntriesPlugin', language='en', app_config=self.app_config_1 + ) + with self.assertNumQueries(53): + plugin_nocache.render_plugin(context, ph) + + with self.assertNumQueries(17): + rendered = plugin.render_plugin(context, ph) + try: + self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1) + except AssertionError: + self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-1') > -1) + self.assertTrue(rendered.find('

first line

') > -1) + self.assertTrue(rendered.find('
-1) + self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1) + def test_plugin_latest(self): pages = self.get_pages() posts = self.get_posts()