Multisite filters

This commit is contained in:
Iacopo Spalletti 2016-06-26 15:33:00 +02:00
parent ade8b189a4
commit 67e3fa0128
No known key found for this signature in database
GPG key ID: BDCBC2EB289F60C6
10 changed files with 199 additions and 63 deletions

View file

@ -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.
******************

View file

@ -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

View file

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig'

View file

@ -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()

View file

@ -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'),
),
]

View file

@ -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

View file

@ -16,4 +16,4 @@
{% endfor %}
</ul>
</div>
{% endspaceless %}
{% endspaceless %}

View file

@ -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'):

View file

@ -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')

View file

@ -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('<p>first line</p>') > -1)
self.assertTrue(rendered.find('<article id="post-first-post"') > -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('<p>second post first line</p>') > -1)
self.assertTrue(rendered.find('<article id="post-second-post"') > -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('<p>second post first line</p>') > -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('<p>second post first line</p>') > -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+<span>\(\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])