Merge pull request #287 from nephila/feature/multisite-filters
WiP: Multisite filters
This commit is contained in:
commit
ecfe85fb1f
17 changed files with 417 additions and 112 deletions
|
@ -10,7 +10,11 @@ History
|
||||||
|
|
||||||
* Dropped support for Django<1.8, django CMS<3.2.
|
* Dropped support for Django<1.8, django CMS<3.2.
|
||||||
* Added liveblog application.
|
* Added liveblog application.
|
||||||
|
* 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.
|
* Added standalone documentation at https://djangocms-blog.readthedocs.io.
|
||||||
|
* Enabled cached version of BlogLatestEntriesPlugin.
|
||||||
|
|
||||||
******************
|
******************
|
||||||
0.8.5 (2016-06-26)
|
0.8.5 (2016-06-26)
|
||||||
|
|
|
@ -96,6 +96,11 @@ HELPER_SETTINGS = dict(
|
||||||
HAYSTACK_CONNECTIONS={
|
HAYSTACK_CONNECTIONS={
|
||||||
'default': {}
|
'default': {}
|
||||||
},
|
},
|
||||||
|
CACHES={
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -262,7 +262,7 @@ class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin):
|
||||||
('Layout', {
|
('Layout', {
|
||||||
'fields': (
|
'fields': (
|
||||||
'config.paginate_by', 'config.url_patterns', 'config.template_prefix',
|
'config.paginate_by', 'config.url_patterns', 'config.template_prefix',
|
||||||
'config.menu_structure',
|
'config.menu_structure', 'config.menu_empty_categories',
|
||||||
),
|
),
|
||||||
'classes': ('collapse',)
|
'classes': ('collapse',)
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -66,6 +66,11 @@ class BlogConfigForm(AppDataForm):
|
||||||
choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE,
|
choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE,
|
||||||
help_text=_('Structure of the django CMS menu')
|
help_text=_('Structure of the django CMS menu')
|
||||||
)
|
)
|
||||||
|
menu_empty_categories = forms.BooleanField(
|
||||||
|
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(
|
sitemap_changefreq = forms.ChoiceField(
|
||||||
label=_('Sitemap changefreq'), required=True,
|
label=_('Sitemap changefreq'), required=True,
|
||||||
choices=get_setting('SITEMAP_CHANGEFREQ'),
|
choices=get_setting('SITEMAP_CHANGEFREQ'),
|
||||||
|
|
|
@ -48,33 +48,16 @@ class BlogCategoryMenu(CMSAttachMenu):
|
||||||
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS):
|
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS):
|
||||||
posts_menu = True
|
posts_menu = True
|
||||||
|
|
||||||
if categories_menu:
|
used_categories = []
|
||||||
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)
|
|
||||||
|
|
||||||
if posts_menu:
|
if posts_menu:
|
||||||
posts = Post.objects
|
posts = Post.objects
|
||||||
if hasattr(self, 'instance') and self.instance:
|
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()
|
posts = posts.active_translations(language).distinct()
|
||||||
for post in posts:
|
for post in posts:
|
||||||
post_id = None
|
post_id = None
|
||||||
parent = None
|
parent = None
|
||||||
|
used_categories.extend(post.categories.values_list('pk', flat=True))
|
||||||
if categories_menu:
|
if categories_menu:
|
||||||
category = post.categories.first()
|
category = post.categories.first()
|
||||||
if category:
|
if category:
|
||||||
|
@ -91,6 +74,28 @@ class BlogCategoryMenu(CMSAttachMenu):
|
||||||
)
|
)
|
||||||
nodes.append(node)
|
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
|
return nodes
|
||||||
|
|
||||||
menu_pool.register_menu(BlogCategoryMenu)
|
menu_pool.register_menu(BlogCategoryMenu)
|
||||||
|
|
|
@ -5,6 +5,8 @@ import os.path
|
||||||
|
|
||||||
from cms.plugin_base import CMSPluginBase
|
from cms.plugin_base import CMSPluginBase
|
||||||
from cms.plugin_pool import plugin_pool
|
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 .forms import LatestEntriesForm
|
||||||
from .models import AuthorEntriesPlugin, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, Post
|
from .models import AuthorEntriesPlugin, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, Post
|
||||||
|
@ -36,7 +38,7 @@ class BlogLatestEntriesPlugin(BlogPlugin):
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(BlogLatestEntriesPlugin, self).render(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')
|
context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT')
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ class BlogLatestEntriesPluginCached(BlogPlugin):
|
||||||
"""
|
"""
|
||||||
Cached plugin which returns the latest published posts
|
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
|
model = LatestPostsPlugin
|
||||||
form = LatestEntriesForm
|
form = LatestEntriesForm
|
||||||
filter_horizontal = ('categories',)
|
filter_horizontal = ('categories',)
|
||||||
|
@ -54,7 +56,7 @@ class BlogLatestEntriesPluginCached(BlogPlugin):
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(BlogLatestEntriesPluginCached, self).render(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')
|
context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT')
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
@ -80,11 +82,8 @@ class BlogTagsPlugin(BlogPlugin):
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(BlogTagsPlugin, self).render(context, instance, placeholder)
|
context = super(BlogTagsPlugin, self).render(context, instance, placeholder)
|
||||||
qs = Post._default_manager
|
qs = instance.post_queryset(context['request'])
|
||||||
qs_post = qs
|
context['tags'] = Post.objects.tag_cloud(queryset=qs.published())
|
||||||
if instance.app_config:
|
|
||||||
qs_post = qs_post.namespace(instance.app_config.namespace)
|
|
||||||
context['tags'] = qs.tag_cloud(queryset=qs_post.published())
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,10 +95,15 @@ class BlogCategoryPlugin(BlogPlugin):
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(BlogCategoryPlugin, self).render(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:
|
if instance.app_config:
|
||||||
qs = qs.namespace(instance.app_config.namespace)
|
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
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,15 +115,13 @@ class BlogArchivePlugin(BlogPlugin):
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(BlogArchivePlugin, self).render(context, instance, placeholder)
|
context = super(BlogArchivePlugin, self).render(context, instance, placeholder)
|
||||||
qs = Post._default_manager
|
qs = instance.post_queryset(context['request'])
|
||||||
qs_post = qs
|
context['dates'] = Post.objects.get_months(queryset=qs.published())
|
||||||
if instance.app_config:
|
|
||||||
qs_post = qs.namespace(instance.app_config.namespace)
|
|
||||||
context['dates'] = qs.get_months(queryset=qs_post.published())
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
plugin_pool.register_plugin(BlogLatestEntriesPlugin)
|
plugin_pool.register_plugin(BlogLatestEntriesPlugin)
|
||||||
|
plugin_pool.register_plugin(BlogLatestEntriesPluginCached)
|
||||||
plugin_pool.register_plugin(BlogAuthorPostsPlugin)
|
plugin_pool.register_plugin(BlogAuthorPostsPlugin)
|
||||||
plugin_pool.register_plugin(BlogTagsPlugin)
|
plugin_pool.register_plugin(BlogTagsPlugin)
|
||||||
plugin_pool.register_plugin(BlogArchivePlugin)
|
plugin_pool.register_plugin(BlogArchivePlugin)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig'
|
default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig'
|
||||||
|
|
|
@ -56,8 +56,10 @@ class TaggedFilterItem(object):
|
||||||
queryset = self.tag_list(other_model, queryset)
|
queryset = self.tag_list(other_model, queryset)
|
||||||
return queryset.values('slug')
|
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
|
from taggit.models import TaggedItem
|
||||||
|
if on_site:
|
||||||
|
queryset = queryset.on_site()
|
||||||
tag_ids = self._taglist(other_model, queryset)
|
tag_ids = self._taglist(other_model, queryset)
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if published:
|
if published:
|
||||||
|
@ -80,20 +82,25 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset):
|
||||||
end_date_field = 'date_published_end'
|
end_date_field = 'date_published_end'
|
||||||
publish_field = 'publish'
|
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) |
|
return self.filter(models.Q(sites__isnull=True) |
|
||||||
models.Q(sites=Site.objects.get_current().pk))
|
models.Q(sites=site.pk))
|
||||||
|
|
||||||
def published(self):
|
def published(self, current_site=True):
|
||||||
queryset = self.published_future()
|
queryset = self.published_future(current_site)
|
||||||
if self.start_date_field:
|
if self.start_date_field:
|
||||||
return queryset.filter(
|
return queryset.filter(
|
||||||
**{'%s__lte' % self.start_date_field: now()})
|
**{'%s__lte' % self.start_date_field: now()})
|
||||||
else:
|
else:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def published_future(self):
|
def published_future(self, current_site=True):
|
||||||
|
if current_site:
|
||||||
queryset = self.on_site()
|
queryset = self.on_site()
|
||||||
|
else:
|
||||||
|
queryset = self
|
||||||
if self.end_date_field:
|
if self.end_date_field:
|
||||||
qfilter = (
|
qfilter = (
|
||||||
models.Q(**{'%s__gte' % self.end_date_field: now()}) |
|
models.Q(**{'%s__gte' % self.end_date_field: now()}) |
|
||||||
|
@ -102,21 +109,29 @@ class GenericDateQuerySet(AppHookConfigTranslatableQueryset):
|
||||||
queryset = queryset.filter(qfilter)
|
queryset = queryset.filter(qfilter)
|
||||||
return queryset.filter(**{self.publish_field: True})
|
return queryset.filter(**{self.publish_field: True})
|
||||||
|
|
||||||
def archived(self):
|
def archived(self, current_site=True):
|
||||||
|
if current_site:
|
||||||
queryset = self.on_site()
|
queryset = self.on_site()
|
||||||
|
else:
|
||||||
|
queryset = self
|
||||||
if self.end_date_field:
|
if self.end_date_field:
|
||||||
qfilter = (
|
qfilter = (
|
||||||
models.Q(**{'%s__lte' % self.end_date_field: now()}) |
|
models.Q(**{'%s__lte' % self.end_date_field: now()})
|
||||||
models.Q(**{'%s__isnull' % self.end_date_field: False})
|
|
||||||
)
|
)
|
||||||
queryset = queryset.filter(qfilter)
|
queryset = queryset.filter(qfilter)
|
||||||
return queryset.filter(**{self.publish_field: True})
|
return queryset.filter(**{self.publish_field: True})
|
||||||
|
|
||||||
def available(self):
|
def available(self, current_site=True):
|
||||||
|
if current_site:
|
||||||
return self.on_site().filter(**{self.publish_field: True})
|
return self.on_site().filter(**{self.publish_field: True})
|
||||||
|
else:
|
||||||
|
return self.filter(**{self.publish_field: True})
|
||||||
|
|
||||||
def filter_by_language(self, language):
|
def filter_by_language(self, language, current_site=True):
|
||||||
|
if current_site:
|
||||||
return self.active_translations(language_code=language).on_site()
|
return self.active_translations(language_code=language).on_site()
|
||||||
|
else:
|
||||||
|
return self.active_translations(language_code=language)
|
||||||
|
|
||||||
|
|
||||||
class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManager):
|
class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManager):
|
||||||
|
@ -127,28 +142,29 @@ class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManage
|
||||||
def get_queryset(self, *args, **kwargs):
|
def get_queryset(self, *args, **kwargs):
|
||||||
return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs)
|
return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs)
|
||||||
|
|
||||||
def published(self):
|
def published(self, current_site=True):
|
||||||
return self.get_queryset().published()
|
return self.get_queryset().published(current_site)
|
||||||
|
|
||||||
def available(self):
|
def available(self, current_site=True):
|
||||||
return self.get_queryset().available()
|
return self.get_queryset().available(current_site)
|
||||||
|
|
||||||
def archived(self):
|
def archived(self, current_site=True):
|
||||||
return self.get_queryset().archived()
|
return self.get_queryset().archived(current_site)
|
||||||
|
|
||||||
def published_future(self):
|
def published_future(self, current_site=True):
|
||||||
return self.get_queryset().published_future()
|
return self.get_queryset().published_future(current_site)
|
||||||
|
|
||||||
def filter_by_language(self, language):
|
def filter_by_language(self, language, current_site=True):
|
||||||
return self.get_queryset().filter_by_language(language)
|
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).
|
Get months with aggregate count (how much posts is in the month).
|
||||||
Results are ordered by date.
|
Results are ordered by date.
|
||||||
"""
|
"""
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
|
if current_site:
|
||||||
queryset = queryset.on_site()
|
queryset = queryset.on_site()
|
||||||
dates_qs = queryset.values_list(queryset.start_date_field, queryset.fallback_date_field)
|
dates_qs = queryset.values_list(queryset.start_date_field, queryset.fallback_date_field)
|
||||||
dates = []
|
dates = []
|
||||||
|
|
30
djangocms_blog/migrations/0023_auto_20160626_1539.py
Normal file
30
djangocms_blog/migrations/0023_auto_20160626_1539.py
Normal 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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -8,6 +8,7 @@ from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableMana
|
||||||
from cms.models import CMSPlugin, PlaceholderField
|
from cms.models import CMSPlugin, PlaceholderField
|
||||||
from django.conf import settings as dj_settings
|
from django.conf import settings as dj_settings
|
||||||
from django.contrib.auth import get_user_model
|
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.cache import cache
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import models
|
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.dispatch import receiver
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_bytes, force_text, python_2_unicode_compatible
|
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.html import escape, strip_tags
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import get_language, ugettext_lazy as _
|
from django.utils.translation import get_language, ugettext_lazy as _
|
||||||
|
@ -76,9 +78,17 @@ class BlogCategory(TranslatableModel):
|
||||||
verbose_name = _('blog category')
|
verbose_name = _('blog category')
|
||||||
verbose_name_plural = _('blog categories')
|
verbose_name_plural = _('blog categories')
|
||||||
|
|
||||||
@property
|
@cached_property
|
||||||
|
def linked_posts(self):
|
||||||
|
return self.blog_posts.namespace(self.app_config.namespace)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
def count(self):
|
def count(self):
|
||||||
return self.blog_posts.namespace(self.app_config.namespace).published().count()
|
return self.linked_posts.published().count()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def count_all_sites(self):
|
||||||
|
return self.linked_posts.published(current_site=False).count()
|
||||||
|
|
||||||
def get_absolute_url(self, lang=None):
|
def get_absolute_url(self, lang=None):
|
||||||
if not lang:
|
if not lang:
|
||||||
|
@ -365,18 +375,24 @@ class BasePostPlugin(CMSPlugin):
|
||||||
app_config = AppHookConfigField(
|
app_config = AppHookConfigField(
|
||||||
BlogConfig, null=True, verbose_name=_('app. config'), blank=True
|
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:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
def post_queryset(self, request=None):
|
def post_queryset(self, request=None, published_only=True):
|
||||||
language = get_language()
|
language = get_language()
|
||||||
posts = Post._default_manager
|
posts = Post.objects
|
||||||
if self.app_config:
|
if self.app_config:
|
||||||
posts = posts.namespace(self.app_config.namespace)
|
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)
|
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
|
||||||
posts = posts.published()
|
not request.toolbar.edit_mode):
|
||||||
|
posts = posts.published(current_site=self.current_site)
|
||||||
return posts.all()
|
return posts.all()
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,14 +400,14 @@ class BasePostPlugin(CMSPlugin):
|
||||||
class LatestPostsPlugin(BasePostPlugin):
|
class LatestPostsPlugin(BasePostPlugin):
|
||||||
latest_posts = models.IntegerField(_('articles'), default=get_setting('LATEST_POSTS'),
|
latest_posts = models.IntegerField(_('articles'), default=get_setting('LATEST_POSTS'),
|
||||||
help_text=_('The number of latests '
|
help_text=_('The number of latests '
|
||||||
u'articles to be displayed.'))
|
'articles to be displayed.'))
|
||||||
tags = TaggableManager(_('filter by tag'), blank=True,
|
tags = TaggableManager(_('filter by tag'), blank=True,
|
||||||
help_text=_('Show only the blog articles tagged with chosen tags.'),
|
help_text=_('Show only the blog articles tagged with chosen tags.'),
|
||||||
related_name='djangocms_blog_latest_post')
|
related_name='djangocms_blog_latest_post')
|
||||||
categories = models.ManyToManyField('djangocms_blog.BlogCategory', blank=True,
|
categories = models.ManyToManyField('djangocms_blog.BlogCategory', blank=True,
|
||||||
verbose_name=_('filter by category'),
|
verbose_name=_('filter by category'),
|
||||||
help_text=_('Show only the blog articles tagged '
|
help_text=_('Show only the blog articles tagged '
|
||||||
u'with chosen categories.'))
|
'with chosen categories.'))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_text(_('%s latest articles by tag') % self.latest_posts)
|
return force_text(_('%s latest articles by tag') % self.latest_posts)
|
||||||
|
@ -402,8 +418,8 @@ class LatestPostsPlugin(BasePostPlugin):
|
||||||
for category in oldinstance.categories.all():
|
for category in oldinstance.categories.all():
|
||||||
self.categories.add(category)
|
self.categories.add(category)
|
||||||
|
|
||||||
def get_posts(self, request):
|
def get_posts(self, request, published_only=True):
|
||||||
posts = self.post_queryset(request)
|
posts = self.post_queryset(request, published_only)
|
||||||
if self.tags.exists():
|
if self.tags.exists():
|
||||||
posts = posts.filter(tags__in=list(self.tags.all()))
|
posts = posts.filter(tags__in=list(self.tags.all()))
|
||||||
if self.categories.exists():
|
if self.categories.exists():
|
||||||
|
@ -428,8 +444,8 @@ class AuthorEntriesPlugin(BasePostPlugin):
|
||||||
def copy_relations(self, oldinstance):
|
def copy_relations(self, oldinstance):
|
||||||
self.authors = oldinstance.authors.all()
|
self.authors = oldinstance.authors.all()
|
||||||
|
|
||||||
def get_posts(self, request):
|
def get_posts(self, request, published_only=True):
|
||||||
posts = self.post_queryset(request)
|
posts = self.post_queryset(request, published_only)
|
||||||
return posts[:self.latest_posts]
|
return posts[:self.latest_posts]
|
||||||
|
|
||||||
def get_authors(self):
|
def get_authors(self):
|
||||||
|
@ -439,7 +455,11 @@ class AuthorEntriesPlugin(BasePostPlugin):
|
||||||
qs = author.djangocms_blog_post_author
|
qs = author.djangocms_blog_post_author
|
||||||
if self.app_config:
|
if self.app_config:
|
||||||
qs = qs.namespace(self.app_config.namespace)
|
qs = qs.namespace(self.app_config.namespace)
|
||||||
count = qs.filter(publish=True).count()
|
if self.current_site:
|
||||||
|
qs = qs.published()
|
||||||
|
else:
|
||||||
|
qs = qs.published(current_site=False)
|
||||||
|
count = qs.count()
|
||||||
if count:
|
if count:
|
||||||
author.count = count
|
author.count = count
|
||||||
return authors
|
return authors
|
||||||
|
|
|
@ -58,6 +58,7 @@ def get_setting(name):
|
||||||
settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100
|
settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100
|
||||||
),
|
),
|
||||||
'BLOG_MENU_TYPES': MENU_TYPES,
|
'BLOG_MENU_TYPES': MENU_TYPES,
|
||||||
|
'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True),
|
||||||
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
|
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
|
||||||
'BLOG_TYPES': meta_settings.OBJECT_TYPES,
|
'BLOG_TYPES': meta_settings.OBJECT_TYPES,
|
||||||
'BLOG_FB_TYPE': getattr(settings, 'BLOG_FB_TYPE', 'Article'),
|
'BLOG_FB_TYPE': getattr(settings, 'BLOG_FB_TYPE', 'Article'),
|
||||||
|
@ -113,6 +114,8 @@ def get_setting(name):
|
||||||
'BLOG_PLUGIN_MODULE_NAME': getattr(settings, 'BLOG_PLUGIN_MODULE_NAME', _('Blog')),
|
'BLOG_PLUGIN_MODULE_NAME': getattr(settings, 'BLOG_PLUGIN_MODULE_NAME', _('Blog')),
|
||||||
'BLOG_LATEST_ENTRIES_PLUGIN_NAME': getattr(
|
'BLOG_LATEST_ENTRIES_PLUGIN_NAME': getattr(
|
||||||
settings, 'BLOG_LATEST_ENTRIES_PLUGIN_NAME', _('Latest Blog Articles')),
|
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(
|
'BLOG_AUTHOR_POSTS_PLUGIN_NAME': getattr(
|
||||||
settings, 'BLOG_AUTHOR_POSTS_PLUGIN_NAME', _('Author Blog Articles')),
|
settings, 'BLOG_AUTHOR_POSTS_PLUGIN_NAME', _('Author Blog Articles')),
|
||||||
'BLOG_TAGS_PLUGIN_NAME': getattr(
|
'BLOG_TAGS_PLUGIN_NAME': getattr(
|
||||||
|
|
|
@ -11,6 +11,8 @@ Global Settings
|
||||||
detail; it's a dictionary with ``size``, ``crop`` and ``upscale`` keys;
|
detail; it's a dictionary with ``size``, ``crop`` and ``upscale`` keys;
|
||||||
(default: ``{'size': '640x120', 'crop': True,'upscale': False}``)
|
(default: ``{'size': '640x120', 'crop': True,'upscale': False}``)
|
||||||
* BLOG_PAGINATION: Number of post per page; (default: ``10``)
|
* 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;
|
* BLOG_LATEST_POSTS: Default number of post in the **Latest post** plugin;
|
||||||
(default: ``5``)
|
(default: ``5``)
|
||||||
* BLOG_POSTS_LIST_TRUNCWORDS_COUNT: Default number of words shown for
|
* 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;
|
* Paginate sizePer-Apphook setting for BLOG_PAGINATION;
|
||||||
* Template prefix: Alternative directory to load the blog templates from;
|
* Template prefix: Alternative directory to load the blog templates from;
|
||||||
* Menu structure: Per-Apphook setting for BLOG_MENU_TYPE
|
* 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 changefreq: Per-Apphook setting for BLOG_SITEMAP_CHANGEFREQ_DEFAULT
|
||||||
* Sitemap priority: Per-Apphook setting for BLOG_SITEMAP_PRIORITY_DEFAULT
|
* Sitemap priority: Per-Apphook setting for BLOG_SITEMAP_PRIORITY_DEFAULT
|
||||||
* Object type: Per-Apphook setting for BLOG_TYPE
|
* Object type: Per-Apphook setting for BLOG_TYPE
|
||||||
|
|
|
@ -154,6 +154,8 @@ class BaseTest(BaseTestCase):
|
||||||
for post in Post.objects.all():
|
for post in Post.objects.all():
|
||||||
post.sites.clear()
|
post.sites.clear()
|
||||||
post.tags.clear()
|
post.tags.clear()
|
||||||
|
post.categories.clear()
|
||||||
|
cache.clear()
|
||||||
super(BaseTest, self).tearDown()
|
super(BaseTest, self).tearDown()
|
||||||
|
|
||||||
def _get_category(self, data, category=None, lang='en'):
|
def _get_category(self, data, category=None, lang='en'):
|
||||||
|
|
|
@ -70,6 +70,8 @@ class MenuTest(BaseTest):
|
||||||
posts = self.get_posts()
|
posts = self.get_posts()
|
||||||
|
|
||||||
cats_url = {}
|
cats_url = {}
|
||||||
|
cats_with_post_url = {}
|
||||||
|
cats_without_post_url = {}
|
||||||
posts_url = {}
|
posts_url = {}
|
||||||
|
|
||||||
languages = ('en', 'it')
|
languages = ('en', 'it')
|
||||||
|
@ -77,6 +79,8 @@ class MenuTest(BaseTest):
|
||||||
for lang in languages:
|
for lang in languages:
|
||||||
with smart_override(lang):
|
with smart_override(lang):
|
||||||
cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(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])
|
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
|
# No item in the menu
|
||||||
|
@ -127,6 +131,27 @@ class MenuTest(BaseTest):
|
||||||
self.assertTrue(cats_url[lang].issubset(nodes_url))
|
self.assertTrue(cats_url[lang].issubset(nodes_url))
|
||||||
self.assertTrue(posts_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):
|
def test_modifier(self):
|
||||||
"""
|
"""
|
||||||
Tests if correct category is selected in the menu
|
Tests if correct category is selected in the menu
|
||||||
|
|
|
@ -438,6 +438,33 @@ class AdminTest(BaseTest):
|
||||||
|
|
||||||
class ModelsTest(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):
|
def test_model_attributes(self):
|
||||||
self.get_pages()
|
self.get_pages()
|
||||||
|
|
||||||
|
@ -611,7 +638,10 @@ class ModelsTest(BaseTest):
|
||||||
# default queryset, published and unpublished posts
|
# default queryset, published and unpublished posts
|
||||||
months = Post.objects.get_months()
|
months = Post.objects.get_months()
|
||||||
for data in 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)
|
self.assertEqual(data['count'], 2)
|
||||||
|
|
||||||
# custom queryset, only published
|
# custom queryset, only published
|
||||||
|
@ -619,9 +649,30 @@ class ModelsTest(BaseTest):
|
||||||
post1.save()
|
post1.save()
|
||||||
months = Post.objects.get_months(Post.objects.published())
|
months = Post.objects.get_months(Post.objects.published())
|
||||||
for data in 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'], 1)
|
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)
|
self.assertEqual(len(Post.objects.available()), 1)
|
||||||
|
|
||||||
# If post is published but publishing date is in the future
|
# If post is published but publishing date is in the future
|
||||||
|
@ -632,6 +683,7 @@ class ModelsTest(BaseTest):
|
||||||
self.assertEqual(len(Post.objects.published()), 1)
|
self.assertEqual(len(Post.objects.published()), 1)
|
||||||
self.assertEqual(len(Post.objects.published_future()), 2)
|
self.assertEqual(len(Post.objects.published_future()), 2)
|
||||||
self.assertEqual(len(Post.objects.archived()), 0)
|
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
|
# 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)
|
post2.date_published = now().replace(year=now().year - 2, month=now().month, day=1)
|
||||||
|
@ -640,10 +692,32 @@ class ModelsTest(BaseTest):
|
||||||
self.assertEqual(len(Post.objects.available()), 2)
|
self.assertEqual(len(Post.objects.available()), 2)
|
||||||
self.assertEqual(len(Post.objects.published()), 1)
|
self.assertEqual(len(Post.objects.published()), 1)
|
||||||
self.assertEqual(len(Post.objects.archived()), 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
|
# counting with language fallback enabled
|
||||||
self._get_post(self._post_data[0]['it'], post1, 'it')
|
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
|
# No fallback
|
||||||
parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = True
|
parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = True
|
||||||
|
@ -706,7 +780,9 @@ class ModelsTest(BaseTest):
|
||||||
request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False)
|
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_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)
|
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')
|
tag = Tag.objects.get(slug='tag-1')
|
||||||
plugin.tags.add(tag)
|
plugin.tags.add(tag)
|
||||||
# unauthenticated users get no post
|
# unauthenticated users get no post
|
||||||
|
@ -714,24 +790,33 @@ class ModelsTest(BaseTest):
|
||||||
# staff users not in edit mode get no post
|
# staff users not in edit mode get no post
|
||||||
self.assertEqual(len(plugin.get_posts(request_auth)), 0)
|
self.assertEqual(len(plugin.get_posts(request_auth)), 0)
|
||||||
# staff users in edit mode get the post
|
# 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.publish = True
|
||||||
post1.save()
|
post1.save()
|
||||||
self.assertEqual(len(plugin.get_posts(request)), 1)
|
self.assertEqual(len(plugin.get_posts(request)), 1)
|
||||||
|
|
||||||
|
|
||||||
|
class ModelsTest2(BaseTest):
|
||||||
|
|
||||||
def test_copy_plugin_latest(self):
|
def test_copy_plugin_latest(self):
|
||||||
post1 = self._get_post(self._post_data[0]['en'])
|
post1 = self._get_post(self._post_data[0]['en'])
|
||||||
post2 = self._get_post(self._post_data[1]['en'])
|
post2 = self._get_post(self._post_data[1]['en'])
|
||||||
tag1 = Tag.objects.create(name='tag 1')
|
tag1 = Tag.objects.create(name='tag 1')
|
||||||
tag2 = Tag.objects.create(name='tag 2')
|
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(tag1)
|
||||||
plugin.tags.add(tag2)
|
plugin.tags.add(tag2)
|
||||||
if CMS_30:
|
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:
|
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)
|
copy_plugins_to(plugins, post2.content)
|
||||||
new = downcast_plugins(post2.content.cmsplugin_set.all())
|
new = downcast_plugins(post2.content.cmsplugin_set.all())
|
||||||
self.assertEqual(set(new[0].tags.all()), set([tag1, tag2]))
|
self.assertEqual(set(new[0].tags.all()), set([tag1, tag2]))
|
||||||
|
@ -741,7 +826,9 @@ class ModelsTest(BaseTest):
|
||||||
post1 = self._get_post(self._post_data[0]['en'])
|
post1 = self._get_post(self._post_data[0]['en'])
|
||||||
post2 = self._get_post(self._post_data[1]['en'])
|
post2 = self._get_post(self._post_data[1]['en'])
|
||||||
request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False)
|
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)
|
plugin.authors.add(self.user)
|
||||||
self.assertEqual(len(plugin.get_posts(request)), 0)
|
self.assertEqual(len(plugin.get_posts(request)), 0)
|
||||||
self.assertEqual(plugin.get_authors()[0].count, 0)
|
self.assertEqual(plugin.get_authors()[0].count, 0)
|
||||||
|
@ -759,12 +846,18 @@ class ModelsTest(BaseTest):
|
||||||
def test_copy_plugin_author(self):
|
def test_copy_plugin_author(self):
|
||||||
post1 = self._get_post(self._post_data[0]['en'])
|
post1 = self._get_post(self._post_data[0]['en'])
|
||||||
post2 = self._get_post(self._post_data[1]['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)
|
plugin.authors.add(self.user)
|
||||||
if CMS_30:
|
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:
|
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)
|
copy_plugins_to(plugins, post2.content)
|
||||||
new = downcast_plugins(post2.content.cmsplugin_set.all())
|
new = downcast_plugins(post2.content.cmsplugin_set.all())
|
||||||
self.assertEqual(set(new[0].authors.all()), set([self.user]))
|
self.assertEqual(set(new[0].authors.all()), set([self.user]))
|
||||||
|
@ -797,13 +890,19 @@ class ModelsTest(BaseTest):
|
||||||
|
|
||||||
self.assertEqual(force_text(post1.categories.first()), 'category 1')
|
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')
|
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')
|
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')
|
self.assertEqual(force_text(plugin.__str__()), 'generic blog plugin')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import os.path
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from cms.api import add_plugin
|
from cms.api import add_plugin
|
||||||
|
from django.contrib.sites.models import SITE_CACHE
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from taggit.models import Tag
|
from taggit.models import Tag
|
||||||
|
@ -16,6 +17,43 @@ from .base import BaseTest
|
||||||
|
|
||||||
class PluginTest(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('<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)
|
||||||
|
|
||||||
|
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('<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)
|
||||||
|
|
||||||
def test_plugin_latest(self):
|
def test_plugin_latest(self):
|
||||||
pages = self.get_pages()
|
pages = self.get_pages()
|
||||||
posts = self.get_posts()
|
posts = self.get_posts()
|
||||||
|
@ -24,7 +62,9 @@ class PluginTest(BaseTest):
|
||||||
posts[0].save()
|
posts[0].save()
|
||||||
ph = pages[0].placeholders.get(slot='content')
|
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')
|
tag = Tag.objects.get(slug='tag-1')
|
||||||
plugin.tags.add(tag)
|
plugin.tags.add(tag)
|
||||||
|
|
||||||
|
@ -34,7 +74,9 @@ class PluginTest(BaseTest):
|
||||||
self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1)
|
self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-1') > -1)
|
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('<p>first line</p>') > -1)
|
||||||
self.assertTrue(rendered.find('<article id="post-first-post"') > -1)
|
self.assertTrue(rendered.find('<article id="post-first-post"') > -1)
|
||||||
self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1)
|
self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1)
|
||||||
|
@ -45,7 +87,9 @@ class PluginTest(BaseTest):
|
||||||
category_2.save()
|
category_2.save()
|
||||||
category_2.set_current_language('en')
|
category_2.set_current_language('en')
|
||||||
posts[1].categories.add(category_2)
|
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)
|
plugin.categories.add(category_2)
|
||||||
|
|
||||||
context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
|
context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
|
||||||
|
@ -54,7 +98,10 @@ class PluginTest(BaseTest):
|
||||||
self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-2') > -1)
|
self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-2') > -1)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
self.assertTrue(rendered.find('cms-plugin-djangocms_blog-post-abstract-2') > -1)
|
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('<p>second post first line</p>') > -1)
|
||||||
self.assertTrue(rendered.find('<article id="post-second-post"') > -1)
|
self.assertTrue(rendered.find('<article id="post-second-post"') > -1)
|
||||||
self.assertTrue(rendered.find(posts[1].get_absolute_url()) > -1)
|
self.assertTrue(rendered.find(posts[1].get_absolute_url()) > -1)
|
||||||
|
@ -77,6 +124,16 @@ class PluginTest(BaseTest):
|
||||||
self.assertEqual(casted_categories.tags.count(), 0)
|
self.assertEqual(casted_categories.tags.count(), 0)
|
||||||
self.assertEqual(casted_categories.categories.count(), 1)
|
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):
|
def test_plugin_tags(self):
|
||||||
pages = self.get_pages()
|
pages = self.get_pages()
|
||||||
posts = self.get_posts()
|
posts = self.get_posts()
|
||||||
|
@ -91,7 +148,9 @@ class PluginTest(BaseTest):
|
||||||
context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
|
context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
|
||||||
rendered = plugin.render_plugin(context, ph)
|
rendered = plugin.render_plugin(context, ph)
|
||||||
for tag in Tag.objects.all():
|
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':
|
if tag.slug == 'test-tag':
|
||||||
rf = '\s+%s\s+<span>\(\s+%s articles' % (tag.name, 2)
|
rf = '\s+%s\s+<span>\(\s+%s articles' % (tag.name, 2)
|
||||||
else:
|
else:
|
||||||
|
@ -99,21 +158,6 @@ class PluginTest(BaseTest):
|
||||||
rx = re.compile(rf)
|
rx = re.compile(rf)
|
||||||
self.assertEqual(len(rx.findall(rendered)), 1)
|
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):
|
def test_blog_archive_plugin(self):
|
||||||
pages = self.get_pages()
|
pages = self.get_pages()
|
||||||
posts = self.get_posts()
|
posts = self.get_posts()
|
||||||
|
@ -199,3 +243,44 @@ class PluginTest2(BaseTest):
|
||||||
|
|
||||||
casted_authors, __ = new[0].get_plugin_instance()
|
casted_authors, __ = new[0].get_plugin_instance()
|
||||||
self.assertEqual(casted_authors.authors.count(), 3)
|
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])
|
||||||
|
|
Loading…
Reference in a new issue