Add support for apphook config

This commit is contained in:
Iacopo Spalletti 2015-09-20 01:11:14 +02:00
parent 78d612a387
commit f6e8e27687
23 changed files with 1308 additions and 428 deletions

View file

@ -18,6 +18,7 @@ HELPER_SETTINGS = dict(
'cmsplugin_filer_image', 'cmsplugin_filer_image',
'taggit', 'taggit',
'taggit_autosuggest', 'taggit_autosuggest',
'aldryn_apphooks_config',
], ],
LANGUAGE_CODE='en', LANGUAGE_CODE='en',
LANGUAGES=( LANGUAGES=(

View file

@ -3,6 +3,7 @@ from __future__ import absolute_import, print_function, unicode_literals
from copy import deepcopy from copy import deepcopy
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
from django import forms from django import forms
from django.conf import settings from django.conf import settings
@ -10,6 +11,8 @@ from django.contrib import admin
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from parler.admin import TranslatableAdmin from parler.admin import TranslatableAdmin
from .cms_appconfig import BlogConfig
from .forms import PostAdminForm
from .models import BlogCategory, Post from .models import BlogCategory, Post
from .settings import get_setting from .settings import get_setting
@ -20,19 +23,22 @@ except ImportError:
pass pass
class BlogCategoryAdmin(EnhancedModelAdminMixin, TranslatableAdmin): class BlogCategoryAdmin(EnhancedModelAdminMixin, ModelAppHookConfig, TranslatableAdmin):
def get_prepopulated_fields(self, request, obj=None): def get_prepopulated_fields(self, request, obj=None):
app_config_default = self._app_config_select(request, obj)
if app_config_default is None and request.method == 'GET':
return {}
return {'slug': ('name',)} return {'slug': ('name',)}
class Media: class Media:
css = { css = {
'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),)
'djangocms_blog_admin.css'),)
} }
class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin, class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
PlaceholderAdminMixin, TranslatableAdmin): ModelAppHookConfig, TranslatableAdmin):
form = PostAdminForm
list_display = ['title', 'author', 'date_published', 'date_published_end'] list_display = ['title', 'author', 'date_published', 'date_published_end']
date_hierarchy = 'date_published' date_hierarchy = 'date_published'
raw_id_fields = ['author'] raw_id_fields = ['author']
@ -40,7 +46,7 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
enhance_exclude = ('main_image', 'tags') enhance_exclude = ('main_image', 'tags')
_fieldsets = [ _fieldsets = [
(None, { (None, {
'fields': [('title', 'categories', 'publish')] 'fields': [('title', 'categories', 'publish', 'app_config')]
}), }),
('Info', { ('Info', {
'fields': (['slug', 'tags'], 'fields': (['slug', 'tags'],
@ -57,6 +63,10 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
}), }),
] ]
app_config_values = {
'default_published': 'publish'
}
def formfield_for_dbfield(self, db_field, **kwargs): def formfield_for_dbfield(self, db_field, **kwargs):
field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs) field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'meta_description': if db_field.name == 'meta_description':
@ -68,11 +78,25 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
return field return field
def get_fieldsets(self, request, obj=None): def get_fieldsets(self, request, obj=None):
app_config_default = self._app_config_select(request, obj)
if app_config_default is None and request.method == 'GET':
return super(PostAdmin, self).get_fieldsets(request, obj)
if not obj:
config = app_config_default
else:
config = obj.app_config
fsets = deepcopy(self._fieldsets) fsets = deepcopy(self._fieldsets)
if get_setting('USE_ABSTRACT'): if config:
fsets[0][1]['fields'].append('abstract') if config.use_abstract:
if not get_setting('USE_PLACEHOLDER'): fsets[0][1]['fields'].append('abstract')
fsets[0][1]['fields'].append('post_text') if not config.use_placeholder:
fsets[0][1]['fields'].append('post_text')
else:
if get_setting('USE_ABSTRACT'):
fsets[0][1]['fields'].append('abstract')
if not get_setting('USE_PLACEHOLDER'):
fsets[0][1]['fields'].append('post_text')
if get_setting('MULTISITE'): if get_setting('MULTISITE'):
fsets[1][1]['fields'][0].append('sites') fsets[1][1]['fields'][0].append('sites')
if request.user.is_superuser: if request.user.is_superuser:
@ -83,7 +107,7 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
return {'slug': ('title',)} return {'slug': ('title',)}
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
if not obj.author_id and get_setting('AUTHOR_DEFAULT'): if not obj.author_id and obj.app_config.set_author:
if get_setting('AUTHOR_DEFAULT') is True: if get_setting('AUTHOR_DEFAULT') is True:
user = request.user user = request.user
else: else:
@ -93,10 +117,18 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
class Media: class Media:
css = { css = {
'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),)
'djangocms_blog_admin.css'),)
} }
class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin):
def get_config_fields(self):
return (
'app_title', 'paginate_by', 'set_author', 'config.default_published',
'config.use_placeholder'
)
admin.site.register(BlogCategory, BlogCategoryAdmin) admin.site.register(BlogCategory, BlogCategoryAdmin)
admin.site.register(Post, PostAdmin) admin.site.register(Post, PostAdmin)
admin.site.register(BlogConfig, BlogConfigAdmin)

View file

@ -1,17 +1,19 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from cms.app_base import CMSApp from aldryn_apphooks_config.app_base import CMSConfigApp
from cms.apphook_pool import apphook_pool from cms.apphook_pool import apphook_pool
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .cms_appconfig import BlogConfig
from .menu import BlogCategoryMenu from .menu import BlogCategoryMenu
class BlogApp(CMSApp): class BlogApp(CMSConfigApp):
name = _('Blog') name = _('Blog')
urls = ['djangocms_blog.urls'] urls = ['djangocms_blog.urls']
app_name = 'djangocms_blog' app_name = 'djangocms_blog'
app_config = BlogConfig
menus = [BlogCategoryMenu] menus = [BlogCategoryMenu]
apphook_pool.register(BlogApp) apphook_pool.register(BlogApp)

View file

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django import forms
from django.db import models
from django.utils.translation import ugettext_lazy as _
from aldryn_apphooks_config.utils import setup_config
from aldryn_apphooks_config.models import AppHookConfig
from app_data import AppDataForm
from parler.models import TranslatableModel
from parler.models import TranslatedFields
from .settings import get_setting
class BlogConfig(TranslatableModel, AppHookConfig):
"""
Adds some translatable, per-app-instance fields.
"""
translations = TranslatedFields(
app_title=models.CharField(_('application title'), max_length=234),
)
def get_app_title(self):
return getattr(self, 'app_title', _('untitled'))
class BlogConfigForm(AppDataForm):
default_published = forms.BooleanField(label=_('Post published by default'), required=False,
initial=get_setting('DEFAULT_PUBLISHED'))
use_placeholder = forms.BooleanField(label=_('Use placeholder and plugins for article body'),
required=False,
initial=get_setting('USE_PLACEHOLDER'))
use_abstract = forms.BooleanField(label=_('Use abstract field'),
required=False,
initial=get_setting('USE_ABSTRACT'))
set_author = forms.BooleanField(label=_('Set author'),
required=False,
help_text=_('Set author by default'),
initial=get_setting('AUTHOR_DEFAULT'))
paginate_by = forms.IntegerField(label=_('Paginate size'),
required=False,
initial=get_setting('PAGINATION'),
help_text=_('When paginating list views, '
'how many articles per page?'))
setup_config(BlogConfigForm, BlogConfig)

View file

@ -7,7 +7,7 @@ from cms.plugin_pool import plugin_pool
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .forms import LatestEntriesForm from .forms import LatestEntriesForm
from .models import AuthorEntriesPlugin, BlogCategory, LatestPostsPlugin, Post from .models import AuthorEntriesPlugin, BlogCategory, LatestPostsPlugin, Post, GenericBlogPlugin
from .settings import get_setting from .settings import get_setting
@ -70,36 +70,47 @@ class BlogAuthorPostsPlugin(BlogPlugin):
class BlogTagsPlugin(BlogPlugin): class BlogTagsPlugin(BlogPlugin):
module = _('Blog') module = _('Blog')
name = _('Tags') name = _('Tags')
model = CMSPlugin model = GenericBlogPlugin
render_template = 'djangocms_blog/plugins/tags.html' render_template = 'djangocms_blog/plugins/tags.html'
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)
context['tags'] = Post.objects.tag_cloud(queryset=Post.objects.published()) 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())
return context return context
class BlogCategoryPlugin(BlogPlugin): class BlogCategoryPlugin(BlogPlugin):
module = _('Blog') module = _('Blog')
name = _('Categories') name = _('Categories')
model = CMSPlugin model = GenericBlogPlugin
render_template = 'djangocms_blog/plugins/categories.html' render_template = 'djangocms_blog/plugins/categories.html'
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)
context['categories'] = BlogCategory.objects.all() qs = BlogCategory._default_manager
if instance.app_config:
qs = qs.namespace(instance.app_config.namespace)
context['categories'] = qs
return context return context
class BlogArchivePlugin(BlogPlugin): class BlogArchivePlugin(BlogPlugin):
module = _('Blog') module = _('Blog')
name = _('Archive') name = _('Archive')
model = CMSPlugin model = GenericBlogPlugin
render_template = 'djangocms_blog/plugins/archive.html' render_template = 'djangocms_blog/plugins/archive.html'
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)
context['dates'] = Post.objects.get_months(queryset=Post.objects.published()) 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())
return context return context

View file

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from aldryn_apphooks_config.utils import get_app_instance
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.contrib.syndication.views import Feed from django.contrib.syndication.views import Feed
@ -12,14 +13,18 @@ from .settings import get_setting
class LatestEntriesFeed(Feed): class LatestEntriesFeed(Feed):
def __call__(self, request, *args, **kwargs):
self.namespace, self.config = get_app_instance(request)
return super(LatestEntriesFeed, self).__call__(request, *args, **kwargs)
def link(self): def link(self):
return reverse('djangocms_blog:posts-latest') return reverse('%s:posts-latest' % self.namespace, current_app=self.namespace)
def title(self): def title(self):
return _('Blog articles on %(site_name)s') % {'site_name': Site.objects.get_current().name} return _('Blog articles on %(site_name)s') % {'site_name': Site.objects.get_current().name}
def items(self, obj=None): def items(self, obj=None):
return Post.objects.published().order_by('-date_published')[:10] return Post.objects.namespace(self.namespace).published().order_by('-date_published')[:10]
def item_title(self, item): def item_title(self, item):
return item.safe_translation_getter('title') return item.safe_translation_getter('title')

View file

@ -3,8 +3,11 @@ from __future__ import absolute_import, print_function, unicode_literals
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from parler.forms import TranslatableModelForm
from taggit_autosuggest.widgets import TagAutoSuggest from taggit_autosuggest.widgets import TagAutoSuggest
from .models import Post, BlogCategory
class LatestEntriesForm(forms.ModelForm): class LatestEntriesForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -16,3 +19,28 @@ class LatestEntriesForm(forms.ModelForm):
'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL,
'djangocms_blog_admin.css'),) 'djangocms_blog_admin.css'),)
} }
class PostAdminForm(TranslatableModelForm):
class Meta:
model = Post
fields = '__all__'
def __init__(self, *args, **kwargs):
super(PostAdminForm, self).__init__(*args, **kwargs)
qs = BlogCategory.objects
if getattr(self.instance, 'app_config_id', None):
qs = qs.namespace(self.instance.app_config.namespace)
elif 'initial' in kwargs and 'app_config' in kwargs['initial']:
qs = qs.namespace(kwargs['initial']['app_config'])
if 'categories' in self.fields:
self.fields['categories'].queryset = qs
if 'app_config' in self.fields:
# Don't allow app_configs to be added here. The correct way to add an
# apphook-config is to create an apphook on a cms Page.
self.fields['app_config'].widget.can_add_related = False

View file

@ -2,10 +2,13 @@
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
import django import django
from aldryn_apphooks_config.managers.parler import (
AppHookConfigTranslatableManager, AppHookConfigTranslatableQueryset
)
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.db import models from django.db import models
from django.utils.timezone import now from django.utils.timezone import now
from parler.managers import TranslatableQuerySet, TranslationManager
try: try:
from collections import Counter from collections import Counter
@ -76,7 +79,7 @@ class TaggedFilterItem(object):
return sorted(tags, key=lambda x: -x.count) return sorted(tags, key=lambda x: -x.count)
class GenericDateQuerySet(TranslatableQuerySet): class GenericDateQuerySet(AppHookConfigTranslatableQueryset):
start_date_field = 'date_published' start_date_field = 'date_published'
end_date_field = 'date_published_end' end_date_field = 'date_published_end'
publish_field = 'publish' publish_field = 'publish'
@ -120,7 +123,7 @@ class GenericDateQuerySet(TranslatableQuerySet):
return self.active_translations(language_code=language).on_site() return self.active_translations(language_code=language).on_site()
class GenericDateTaggedManager(TaggedFilterItem, TranslationManager): class GenericDateTaggedManager(TaggedFilterItem, AppHookConfigTranslatableManager):
use_for_related_fields = True use_for_related_fields = True
queryset_class = GenericDateQuerySet queryset_class = GenericDateQuerySet

View file

@ -3,11 +3,11 @@ from __future__ import absolute_import, print_function, unicode_literals
from cms.menu_bases import CMSAttachMenu from cms.menu_bases import CMSAttachMenu
from django.db.models.signals import post_delete, post_save from django.db.models.signals import post_delete, post_save
from django.utils.translation import get_language, ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _, get_language_from_request
from menus.base import Modifier, NavigationNode from menus.base import Modifier, NavigationNode
from menus.menu_pool import menu_pool from menus.menu_pool import menu_pool
from .models import BlogCategory from .models import BlogCategory, Post
class BlogCategoryMenu(CMSAttachMenu): class BlogCategoryMenu(CMSAttachMenu):
@ -15,54 +15,42 @@ class BlogCategoryMenu(CMSAttachMenu):
def get_nodes(self, request): def get_nodes(self, request):
nodes = [] nodes = []
qs = BlogCategory.objects.translated(get_language())
qs = qs.order_by('parent__id', 'translations__name') language = get_language_from_request(request, check_path=True)
for category in qs:
categories = BlogCategory.objects
if hasattr(self, 'instance') and self.instance:
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( node = NavigationNode(
category.name, category.name,
category.get_absolute_url(), category.get_absolute_url(),
category.pk, '%s-%s' % (category.__class__.__name__, category.pk),
category.parent_id ('%s-%s' % (category.__class__.__name__, category.parent.id) if category.parent
else None)
) )
nodes.append(node) nodes.append(node)
posts = Post.objects
if hasattr(self, 'instance') and self.instance:
posts = posts.namespace(self.instance.application_namespace)
posts = posts.active_translations(language).distinct()
for post in posts:
category = post.categories.first()
node = NavigationNode(
post.get_title(),
post.get_absolute_url(language),
'%s-%s' % (post.__class__.__name__, category.pk),
'%s-%s' % (category.__class__.__name__, category.pk)
)
nodes.append(node)
return nodes return nodes
menu_pool.register_menu(BlogCategoryMenu) menu_pool.register_menu(BlogCategoryMenu)
class BlogNavModifier(Modifier):
"""
This navigation modifier makes sure that when
a particular blog post is viewed,
a corresponding category is selected in menu
"""
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
if post_cut:
return nodes
if not hasattr(request, 'toolbar'):
return nodes
models = ('djangocms_blog.post', 'djangocms_blog.blogcategory')
model = request.toolbar.get_object_model()
if model not in models:
return nodes
if model == 'djangocms_blog.blogcategory':
cat = request.toolbar.obj
else:
cat = request.toolbar.obj.categories.first()
if not cat:
return nodes
for node in nodes:
if (node.namespace.startswith(BlogCategoryMenu.__name__) and
cat.pk == node.id):
node.selected = True
# no break here because django-cms maintains two menu structures
# for every apphook (attached to published page and draft page)
return nodes
menu_pool.register_modifier(BlogNavModifier)
def clear_menu_cache(**kwargs): def clear_menu_cache(**kwargs):
menu_pool.clear(all=True) menu_pool.clear(all=True)

View file

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import aldryn_apphooks_config.fields
import app_data.fields
import djangocms_text_ckeditor.fields
from cms.models import Page
from cms.utils.conf import get_languages
from django.db import models, migrations
def forwards(apps, schema_editor):
BlogConfig = apps.get_model('djangocms_blog', 'BlogConfig')
Post = apps.get_model('djangocms_blog', 'Post')
BlogCategory = apps.get_model('djangocms_blog', 'BlogCategory')
GenericBlogPlugin = apps.get_model('djangocms_blog', 'GenericBlogPlugin')
LatestPostsPlugin = apps.get_model('djangocms_blog', 'LatestPostsPlugin')
AuthorEntriesPlugin = apps.get_model('djangocms_blog', 'AuthorEntriesPlugin')
config = None
for page in Page.objects.drafts().filter(application_urls='BlogApp'):
config = BlogConfig.objects.create(namespace=page.application_namespace)
for lang in get_languages():
config.create_translation(lang, app_title='Blog')
if config:
for model in (Post, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, AuthorEntriesPlugin):
for item in model.objects.all():
item.app_config = config
item.save()
def backwards(apps, schema_editor):
# No need for backward data migration
pass
class Migration(migrations.Migration):
dependencies = [
('cms', '__latest__'),
('djangocms_blog', '0009_latestpostsplugin_tags_new'),
]
operations = [
migrations.CreateModel(
name='BlogConfig',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('type', models.CharField(verbose_name='type', max_length=100)),
('namespace', models.CharField(default=None, verbose_name='instance namespace', unique=True, max_length=100)),
('app_data', app_data.fields.AppDataField(editable=False, default='{}')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='BlogConfigTranslation',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('language_code', models.CharField(db_index=True, verbose_name='Language', max_length=15)),
('app_title', models.CharField(verbose_name='application title', max_length=234)),
('master', models.ForeignKey(editable=False, to='djangocms_blog.BlogConfig', related_name='translations', null=True)),
],
options={
'verbose_name': 'blog config Translation',
'db_table': 'djangocms_blog_blogconfig_translation',
'default_permissions': (),
'db_tablespace': '',
'managed': True,
},
),
migrations.CreateModel(
name='GenericBlogPlugin',
fields=[
('cmsplugin_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, auto_created=True, to='cms.CMSPlugin')),
('app_config', aldryn_apphooks_config.fields.AppHookConfigField(verbose_name='app. config', blank=True, to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default')),
],
options={
'abstract': False,
},
bases=('cms.cmsplugin',),
),
migrations.AlterField(
model_name='posttranslation',
name='abstract',
field=djangocms_text_ckeditor.fields.HTMLField(default='', verbose_name='abstract', blank=True),
),
migrations.AddField(
model_name='authorentriesplugin',
name='app_config',
field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, blank=True, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default'),
preserve_default=False,
),
migrations.AddField(
model_name='blogcategory',
name='app_config',
field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default'),
preserve_default=False,
),
migrations.AddField(
model_name='latestpostsplugin',
name='app_config',
field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, blank=True, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default'),
preserve_default=False,
),
migrations.AddField(
model_name='post',
name='app_config',
field=aldryn_apphooks_config.fields.AppHookConfigField(default=None, verbose_name='app. config', to='djangocms_blog.BlogConfig', help_text='When selecting a value, the form is reloaded to get the updated default'),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name='blogconfigtranslation',
unique_together=set([('language_code', 'master')]),
),
migrations.RunPython(forwards, backwards)
]

View file

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager
from aldryn_apphooks_config.fields import AppHookConfigField
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.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -13,10 +15,10 @@ from django.utils.translation import get_language, ugettext_lazy as _
from djangocms_text_ckeditor.fields import HTMLField from djangocms_text_ckeditor.fields import HTMLField
from filer.fields.image import FilerImageField from filer.fields.image import FilerImageField
from meta_mixin.models import ModelMeta from meta_mixin.models import ModelMeta
from parler.managers import TranslationManager
from parler.models import TranslatableModel, TranslatedFields from parler.models import TranslatableModel, TranslatedFields
from taggit_autosuggest.managers import TaggableManager from taggit_autosuggest.managers import TaggableManager
from .cms_appconfig import BlogConfig
from .managers import GenericDateTaggedManager from .managers import GenericDateTaggedManager
from .settings import get_setting from .settings import get_setting
@ -28,10 +30,10 @@ class BlogCategory(TranslatableModel):
""" """
Blog category Blog category
""" """
parent = models.ForeignKey('self', verbose_name=_('parent'), null=True, parent = models.ForeignKey('self', verbose_name=_('parent'), null=True, blank=True)
blank=True)
date_created = models.DateTimeField(_('created at'), auto_now_add=True) date_created = models.DateTimeField(_('created at'), auto_now_add=True)
date_modified = models.DateTimeField(_('modified at'), auto_now=True) date_modified = models.DateTimeField(_('modified at'), auto_now=True)
app_config = AppHookConfigField(BlogConfig, verbose_name=_('app. config'))
translations = TranslatedFields( translations = TranslatedFields(
name=models.CharField(_('name'), max_length=255), name=models.CharField(_('name'), max_length=255),
@ -39,7 +41,7 @@ class BlogCategory(TranslatableModel):
meta={'unique_together': (('language_code', 'slug'),)} meta={'unique_together': (('language_code', 'slug'),)}
) )
objects = TranslationManager() objects = AppHookConfigTranslatableManager()
class Meta: class Meta:
verbose_name = _('blog category') verbose_name = _('blog category')
@ -47,16 +49,23 @@ class BlogCategory(TranslatableModel):
@property @property
def count(self): def count(self):
return self.blog_posts.published().count() return self.blog_posts.namespace(self.app_config.namespace).published().count()
def get_absolute_url(self): def get_absolute_url(self, lang=None):
lang = get_language() if not lang:
if self.has_translation(lang): lang = get_language()
if self.has_translation(lang, ):
slug = self.safe_translation_getter('slug', language_code=lang) slug = self.safe_translation_getter('slug', language_code=lang)
return reverse('djangocms_blog:posts-category', kwargs={'category': slug}) return reverse(
'%s:posts-category' % self.app_config.namespace,
kwargs={'category': slug},
current_app=self.app_config.namespace
)
# in case category doesn't exist in this language, gracefully fallback # in case category doesn't exist in this language, gracefully fallback
# to posts-latest # to posts-latest
return reverse('djangocms_blog:posts-latest') return reverse(
'%s:posts-latest' % self.app_config.namespace, current_app=self.app_config.namespace
)
def __str__(self): def __str__(self):
return self.safe_translation_getter('name') return self.safe_translation_getter('name')
@ -108,6 +117,7 @@ class Post(ModelMeta, TranslatableModel):
help_text=_('Select sites in which to show the post. ' help_text=_('Select sites in which to show the post. '
u'If none is set it will be ' u'If none is set it will be '
u'visible in all the configured sites.')) u'visible in all the configured sites.'))
app_config = AppHookConfigField(BlogConfig, verbose_name=_('app. config'))
translations = TranslatedFields( translations = TranslatedFields(
title=models.CharField(_('title'), max_length=255), title=models.CharField(_('title'), max_length=255),
@ -165,19 +175,21 @@ class Post(ModelMeta, TranslatableModel):
def __str__(self): def __str__(self):
return self.safe_translation_getter('title') return self.safe_translation_getter('title')
def get_absolute_url(self): def get_absolute_url(self, lang=None):
if not lang:
lang = get_language()
kwargs = {'year': self.date_published.year, kwargs = {'year': self.date_published.year,
'month': '%02d' % self.date_published.month, 'month': '%02d' % self.date_published.month,
'day': '%02d' % self.date_published.day, 'day': '%02d' % self.date_published.day,
'slug': self.safe_translation_getter('slug', 'slug': self.safe_translation_getter('slug',
language_code=get_language(), language_code=lang,
any_language=True)} any_language=True)}
return reverse('djangocms_blog:post-detail', kwargs=kwargs) return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)
def save(self, *args, **kwargs): def save_translation(self, translation, *args, **kwargs):
if not self.slug and self.title: if not translation.slug and translation.title:
self.slug = slugify(self.title) translation.slug = slugify(translation.title)
super(Post, self).save(*args, **kwargs) super(Post, self).save_translation(translation, *args, **kwargs)
def get_title(self): def get_title(self):
title = self.safe_translation_getter('meta_title', any_language=True) title = self.safe_translation_getter('meta_title', any_language=True)
@ -230,7 +242,10 @@ class BasePostPlugin(CMSPlugin):
def post_queryset(self, request=None): def post_queryset(self, request=None):
language = get_language() language = get_language()
posts = Post._default_manager.active_translations(language_code=language) posts = Post._default_manager
if self.app_config:
posts = posts.namespace(self.app_config.namespace)
posts = posts.active_translations(language_code=language)
if not request or not getattr(request, 'toolbar', False) or not request.toolbar.edit_mode: if not request or not getattr(request, 'toolbar', False) or not request.toolbar.edit_mode:
posts = posts.published() posts = posts.published()
return posts return posts
@ -240,7 +255,7 @@ class BasePostPlugin(CMSPlugin):
class LatestPostsPlugin(BasePostPlugin): class LatestPostsPlugin(BasePostPlugin):
app_config = AppHookConfigField(BlogConfig, verbose_name=_('app. config'), blank=True)
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.')) u'articles to be displayed.'))
@ -269,6 +284,7 @@ class LatestPostsPlugin(BasePostPlugin):
class AuthorEntriesPlugin(BasePostPlugin): class AuthorEntriesPlugin(BasePostPlugin):
app_config = AppHookConfigField(BlogConfig, verbose_name=_('app. config'), blank=True)
authors = models.ManyToManyField( authors = models.ManyToManyField(
dj_settings.AUTH_USER_MODEL, verbose_name=_('authors'), dj_settings.AUTH_USER_MODEL, verbose_name=_('authors'),
limit_choices_to={'djangocms_blog_post_author__publish': True} limit_choices_to={'djangocms_blog_post_author__publish': True}
@ -292,6 +308,17 @@ class AuthorEntriesPlugin(BasePostPlugin):
authors = self.authors.all() authors = self.authors.all()
for author in authors: for author in authors:
author.count = 0 author.count = 0
if author.djangocms_blog_post_author.filter(publish=True).exists(): qs = author.djangocms_blog_post_author
author.count = author.djangocms_blog_post_author.filter(publish=True).count() if self.app_config:
qs = qs.namespace(self.app_config.namespace)
count = qs.filter(publish=True).count()
if count:
author.count = count
return authors return authors
class GenericBlogPlugin(BasePostPlugin):
app_config = AppHookConfigField(BlogConfig, verbose_name=_('app. config'), blank=True)
def __str__(self):
return _('generic blog plugin')

View file

@ -52,5 +52,6 @@ def get_setting(name):
'BLOG_USE_PLACEHOLDER': getattr(settings, 'BLOG_USE_PLACEHOLDER', True), 'BLOG_USE_PLACEHOLDER': getattr(settings, 'BLOG_USE_PLACEHOLDER', True),
'BLOG_MULTISITE': getattr(settings, 'BLOG_MULTISITE', True), 'BLOG_MULTISITE': getattr(settings, 'BLOG_MULTISITE', True),
'BLOG_AUTHOR_DEFAULT': getattr(settings, 'BLOG_AUTHOR_DEFAULT', True), 'BLOG_AUTHOR_DEFAULT': getattr(settings, 'BLOG_AUTHOR_DEFAULT', True),
'BLOG_DEFAULT_PUBLISHED': getattr(settings, 'BLOG_DEFAULT_PUBLISHED', False),
} }
return default['BLOG_%s' % name] return default['BLOG_%s' % name]

View file

@ -0,0 +1,286 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'BlogConfigTranslation'
db.create_table('djangocms_blog_blogconfig_translation', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('language_code', self.gf('django.db.models.fields.CharField')(db_index=True, max_length=15)),
('app_title', self.gf('django.db.models.fields.CharField')(max_length=234)),
('master', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['djangocms_blog.BlogConfig'], related_name='translations', null=True)),
))
db.send_create_signal('djangocms_blog', ['BlogConfigTranslation'])
# Adding unique constraint on 'BlogConfigTranslation', fields ['language_code', 'master']
db.create_unique('djangocms_blog_blogconfig_translation', ['language_code', 'master_id'])
# Adding model 'BlogConfig'
db.create_table('djangocms_blog_blogconfig', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('type', self.gf('django.db.models.fields.CharField')(max_length=100)),
('namespace', self.gf('django.db.models.fields.CharField')(default=None, max_length=100, unique=True)),
('app_data', self.gf('app_data.fields.AppDataField')(default='{}')),
))
db.send_create_signal('djangocms_blog', ['BlogConfig'])
# Adding model 'GenericBlogPlugin'
db.create_table('djangocms_blog_genericblogplugin', (
('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(primary_key=True, to=orm['cms.CMSPlugin'], unique=True)),
('app_config', self.gf('aldryn_apphooks_config.fields.AppHookConfigField')(blank=True, null=True, to=orm['djangocms_blog.BlogConfig'])),
))
db.send_create_signal('djangocms_blog', ['GenericBlogPlugin'])
# Adding field 'AuthorEntriesPlugin.app_config'
db.add_column('djangocms_blog_authorentriesplugin', 'app_config',
self.gf('aldryn_apphooks_config.fields.AppHookConfigField')(default=None, blank=True, null=True, to=orm['djangocms_blog.BlogConfig']),
keep_default=False)
# Adding field 'Post.app_config'
db.add_column('djangocms_blog_post', 'app_config',
self.gf('aldryn_apphooks_config.fields.AppHookConfigField')(to=orm['djangocms_blog.BlogConfig'], null=True, default=None),
keep_default=False)
# Adding field 'BlogCategory.app_config'
db.add_column('djangocms_blog_blogcategory', 'app_config',
self.gf('aldryn_apphooks_config.fields.AppHookConfigField')(to=orm['djangocms_blog.BlogConfig'], null=True, default=None),
keep_default=False)
# Adding field 'LatestPostsPlugin.app_config'
db.add_column('djangocms_blog_latestpostsplugin', 'app_config',
self.gf('aldryn_apphooks_config.fields.AppHookConfigField')(default=None, null=True, blank=True, to=orm['djangocms_blog.BlogConfig']),
keep_default=False)
def backwards(self, orm):
# Removing unique constraint on 'BlogConfigTranslation', fields ['language_code', 'master']
db.delete_unique('djangocms_blog_blogconfig_translation', ['language_code', 'master_id'])
# Deleting model 'BlogConfigTranslation'
db.delete_table('djangocms_blog_blogconfig_translation')
# Deleting model 'BlogConfig'
db.delete_table('djangocms_blog_blogconfig')
# Deleting model 'GenericBlogPlugin'
db.delete_table('djangocms_blog_genericblogplugin')
# Deleting field 'AuthorEntriesPlugin.app_config'
db.delete_column('djangocms_blog_authorentriesplugin', 'app_config_id')
# Deleting field 'Post.app_config'
db.delete_column('djangocms_blog_post', 'app_config_id')
# Deleting field 'BlogCategory.app_config'
db.delete_column('djangocms_blog_blogcategory', 'app_config_id')
# Deleting field 'LatestPostsPlugin.app_config'
db.delete_column('djangocms_blog_latestpostsplugin', 'app_config_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['auth.Permission']"})
},
'auth.permission': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission', 'ordering': "('content_type__app_label', 'content_type__model', 'codename')"},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'blank': 'True', 'max_length': '75'}),
'first_name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '30'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'related_name': "'user_set'", 'to': "orm['auth.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '30'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'related_name': "'user_set'", 'to': "orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'max_length': '30', 'unique': 'True'})
},
'cms.cmsplugin': {
'Meta': {'object_name': 'CMSPlugin'},
'changed_date': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'to': "orm['cms.CMSPlugin']", 'null': 'True'}),
'path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True'}),
'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
'plugin_type': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50'}),
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'blank': 'True', 'null': 'True'})
},
'cms.placeholder': {
'Meta': {'object_name': 'Placeholder'},
'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slot': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255'})
},
'cmsplugin_filer_image.thumbnailoption': {
'Meta': {'object_name': 'ThumbnailOption', 'ordering': "('width', 'height')"},
'crop': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'height': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'upscale': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {})
},
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'ordering': "('name',)", 'db_table': "'django_content_type'", 'object_name': 'ContentType'},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'djangocms_blog.authorentriesplugin': {
'Meta': {'object_name': 'AuthorEntriesPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'})
},
'djangocms_blog.blogcategory': {
'Meta': {'object_name': 'BlogCategory'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'to': "orm['djangocms_blog.BlogConfig']"}),
'date_created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogCategory']", 'null': 'True'})
},
'djangocms_blog.blogcategorytranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), ('language_code', 'master')]", 'object_name': 'BlogCategoryTranslation', 'db_table': "'djangocms_blog_blogcategory_translation'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.BlogCategory']", 'related_name': "'translations'", 'null': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.SlugField', [], {'blank': 'True', 'max_length': '50'})
},
'djangocms_blog.blogconfig': {
'Meta': {'object_name': 'BlogConfig'},
'app_data': ('app_data.fields.AppDataField', [], {'default': "'{}'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'namespace': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '100', 'unique': 'True'}),
'paginate_by': ('django.db.models.fields.PositiveIntegerField', [], {'default': '10'}),
'set_author': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'djangocms_blog.blogconfigtranslation': {
'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'BlogConfigTranslation', 'db_table': "'djangocms_blog_blogconfig_translation'"},
'app_title': ('django.db.models.fields.CharField', [], {'max_length': '234'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.BlogConfig']", 'related_name': "'translations'", 'null': 'True'})
},
'djangocms_blog.genericblogplugin': {
'Meta': {'object_name': 'GenericBlogPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'})
},
'djangocms_blog.latestpostsplugin': {
'Meta': {'object_name': 'LatestPostsPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['djangocms_blog.BlogCategory']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'})
},
'djangocms_blog.post': {
'Meta': {'object_name': 'Post', 'ordering': "('-date_published', '-date_created')"},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'to': "orm['djangocms_blog.BlogConfig']"}),
'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_author'", 'to': "orm['auth.User']", 'null': 'True'}),
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['djangocms_blog.BlogCategory']", 'related_name': "'blog_posts'"}),
'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'related_name': "'post_content'", 'null': 'True'}),
'date_created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'date_published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'date_published_end': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'null': 'True'}),
'enable_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'main_image': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_image'", 'to': "orm['filer.Image']", 'null': 'True'}),
'main_image_full': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_full'", 'to': "orm['cmsplugin_filer_image.ThumbnailOption']", 'null': 'True'}),
'main_image_thumbnail': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_thumbnail'", 'to': "orm['cmsplugin_filer_image.ThumbnailOption']", 'null': 'True'}),
'publish': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['sites.Site']", 'null': 'True'})
},
'djangocms_blog.posttranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), ('language_code', 'master')]", 'object_name': 'PostTranslation', 'db_table': "'djangocms_blog_post_translation'"},
'abstract': ('djangocms_text_ckeditor.fields.HTMLField', [], {'blank': 'True', 'default': "''"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.Post']", 'related_name': "'translations'", 'null': 'True'}),
'meta_description': ('django.db.models.fields.TextField', [], {'blank': 'True', 'default': "''"}),
'meta_keywords': ('django.db.models.fields.TextField', [], {'blank': 'True', 'default': "''"}),
'meta_title': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'default': "''"}),
'post_text': ('djangocms_text_ckeditor.fields.HTMLField', [], {'blank': 'True', 'default': "''"}),
'slug': ('django.db.models.fields.SlugField', [], {'blank': 'True', 'max_length': '50'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'filer.file': {
'Meta': {'object_name': 'File'},
'_file_size': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True', 'null': 'True'}),
'file': ('django.db.models.fields.files.FileField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'to': "orm['filer.Folder']", 'null': 'True'}),
'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'default': "''"}),
'original_filename': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'to': "orm['auth.User']", 'null': 'True'}),
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'related_name': "'polymorphic_filer.file_set+'", 'null': 'True'}),
'sha1': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '40', 'default': "''"}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'})
},
'filer.folder': {
'Meta': {'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder', 'ordering': "('name',)"},
'created_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'to': "orm['auth.User']", 'null': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'to': "orm['filer.Folder']", 'null': 'True'}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'})
},
'filer.image': {
'Meta': {'object_name': 'Image'},
'_height': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'_width': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'author': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'date_taken': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'null': 'True'}),
'default_alt_text': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'default_caption': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['filer.File']", 'unique': 'True'}),
'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'subject_location': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '64', 'default': 'None', 'null': 'True'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'db_table': "'django_site'", 'object_name': 'Site'},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['djangocms_blog']

View file

@ -0,0 +1,234 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
from cms.models import Page
from cms.utils.conf import get_languages
class Migration(DataMigration):
def forwards(self, orm):
BlogConfig = orm['djangocms_blog.BlogConfig']
Post = orm['djangocms_blog.Post']
BlogCategory = orm['djangocms_blog.BlogCategory']
GenericBlogPlugin = orm['djangocms_blog.GenericBlogPlugin']
LatestPostsPlugin = orm['djangocms_blog.LatestPostsPlugin']
AuthorEntriesPlugin = orm['djangocms_blog.AuthorEntriesPlugin']
config = None
for page in Page.objects.drafts().filter(application_urls='BlogApp'):
config = BlogConfig.objects.create(namespace=page.application_namespace)
for lang in get_languages():
config.create_translation(lang, app_title='Blog')
if config:
for model in (Post, BlogCategory, GenericBlogPlugin, LatestPostsPlugin, AuthorEntriesPlugin):
for item in model.objects.all():
item.app_config = config
item.save()
def backwards(self, orm):
# No need for backward data migration
pass
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['auth.Permission']"})
},
'auth.permission': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission', 'ordering': "('content_type__app_label', 'content_type__model', 'codename')"},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'blank': 'True', 'max_length': '75'}),
'first_name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '30'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'related_name': "'user_set'", 'to': "orm['auth.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '30'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'related_name': "'user_set'", 'to': "orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'max_length': '30', 'unique': 'True'})
},
'cms.cmsplugin': {
'Meta': {'object_name': 'CMSPlugin'},
'changed_date': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'to': "orm['cms.CMSPlugin']", 'null': 'True'}),
'path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True'}),
'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
'plugin_type': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50'}),
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'blank': 'True', 'null': 'True'})
},
'cms.placeholder': {
'Meta': {'object_name': 'Placeholder'},
'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slot': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255'})
},
'cmsplugin_filer_image.thumbnailoption': {
'Meta': {'object_name': 'ThumbnailOption', 'ordering': "('width', 'height')"},
'crop': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'height': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'upscale': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {})
},
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'ordering': "('name',)", 'db_table': "'django_content_type'", 'object_name': 'ContentType'},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'djangocms_blog.authorentriesplugin': {
'Meta': {'object_name': 'AuthorEntriesPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'})
},
'djangocms_blog.blogcategory': {
'Meta': {'object_name': 'BlogCategory'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'to': "orm['djangocms_blog.BlogConfig']"}),
'date_created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogCategory']", 'null': 'True'})
},
'djangocms_blog.blogcategorytranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), ('language_code', 'master')]", 'object_name': 'BlogCategoryTranslation', 'db_table': "'djangocms_blog_blogcategory_translation'"},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.BlogCategory']", 'related_name': "'translations'", 'null': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.SlugField', [], {'blank': 'True', 'max_length': '50'})
},
'djangocms_blog.blogconfig': {
'Meta': {'object_name': 'BlogConfig'},
'app_data': ('app_data.fields.AppDataField', [], {'default': "'{}'"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'namespace': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '100', 'unique': 'True'}),
'paginate_by': ('django.db.models.fields.PositiveIntegerField', [], {'default': '10'}),
'set_author': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'djangocms_blog.blogconfigtranslation': {
'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'BlogConfigTranslation', 'db_table': "'djangocms_blog_blogconfig_translation'"},
'app_title': ('django.db.models.fields.CharField', [], {'max_length': '234'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.BlogConfig']", 'related_name': "'translations'", 'null': 'True'})
},
'djangocms_blog.genericblogplugin': {
'Meta': {'object_name': 'GenericBlogPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'})
},
'djangocms_blog.latestpostsplugin': {
'Meta': {'object_name': 'LatestPostsPlugin'},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'blank': 'True', 'to': "orm['djangocms_blog.BlogConfig']"}),
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['djangocms_blog.BlogCategory']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['cms.CMSPlugin']", 'unique': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'})
},
'djangocms_blog.post': {
'Meta': {'object_name': 'Post', 'ordering': "('-date_published', '-date_created')"},
'app_config': ('aldryn_apphooks_config.fields.AppHookConfigField', [], {'to': "orm['djangocms_blog.BlogConfig']"}),
'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_author'", 'to': "orm['auth.User']", 'null': 'True'}),
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['djangocms_blog.BlogCategory']", 'related_name': "'blog_posts'"}),
'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'related_name': "'post_content'", 'null': 'True'}),
'date_created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'date_published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'date_published_end': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'null': 'True'}),
'enable_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'main_image': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_image'", 'to': "orm['filer.Image']", 'null': 'True'}),
'main_image_full': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_full'", 'to': "orm['cmsplugin_filer_image.ThumbnailOption']", 'null': 'True'}),
'main_image_thumbnail': ('django.db.models.fields.related.ForeignKey', [], {'on_delete': 'models.SET_NULL', 'blank': 'True', 'related_name': "'djangocms_blog_post_thumbnail'", 'to': "orm['cmsplugin_filer_image.ThumbnailOption']", 'null': 'True'}),
'publish': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'blank': 'True', 'to': "orm['sites.Site']", 'null': 'True'})
},
'djangocms_blog.posttranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), ('language_code', 'master')]", 'object_name': 'PostTranslation', 'db_table': "'djangocms_blog_post_translation'"},
'abstract': ('djangocms_text_ckeditor.fields.HTMLField', [], {'blank': 'True', 'default': "''"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '15'}),
'master': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangocms_blog.Post']", 'related_name': "'translations'", 'null': 'True'}),
'meta_description': ('django.db.models.fields.TextField', [], {'blank': 'True', 'default': "''"}),
'meta_keywords': ('django.db.models.fields.TextField', [], {'blank': 'True', 'default': "''"}),
'meta_title': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'default': "''"}),
'post_text': ('djangocms_text_ckeditor.fields.HTMLField', [], {'blank': 'True', 'default': "''"}),
'slug': ('django.db.models.fields.SlugField', [], {'blank': 'True', 'max_length': '50'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'filer.file': {
'Meta': {'object_name': 'File'},
'_file_size': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True', 'null': 'True'}),
'file': ('django.db.models.fields.files.FileField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'to': "orm['filer.Folder']", 'null': 'True'}),
'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'default': "''"}),
'original_filename': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'to': "orm['auth.User']", 'null': 'True'}),
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'related_name': "'polymorphic_filer.file_set+'", 'null': 'True'}),
'sha1': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '40', 'default': "''"}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'})
},
'filer.folder': {
'Meta': {'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder', 'ordering': "('name',)"},
'created_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'to': "orm['auth.User']", 'null': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'to': "orm['filer.Folder']", 'null': 'True'}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'auto_now_add': 'True'})
},
'filer.image': {
'Meta': {'object_name': 'Image'},
'_height': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'_width': ('django.db.models.fields.IntegerField', [], {'blank': 'True', 'null': 'True'}),
'author': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'date_taken': ('django.db.models.fields.DateTimeField', [], {'blank': 'True', 'null': 'True'}),
'default_alt_text': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'default_caption': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '255', 'null': 'True'}),
'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'primary_key': 'True', 'to': "orm['filer.File']", 'unique': 'True'}),
'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'subject_location': ('django.db.models.fields.CharField', [], {'blank': 'True', 'max_length': '64', 'default': 'None', 'null': 'True'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'db_table': "'django_site'", 'object_name': 'Site'},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['djangocms_blog']

View file

@ -21,7 +21,7 @@
</div> </div>
{% endif %} {% endif %}
{% endspaceless %} {% endspaceless %}
{% if use_placeholder %} {% if post.app_config.use_placeholder %}
<div class="blog-content">{% render_placeholder post.content %}</div> <div class="blog-content">{% render_placeholder post.content %}</div>
{% else %} {% else %}
<div class="blog-content">{% render_model post "post_text" "post_text" %}</div> <div class="blog-content">{% render_model post "post_text" "post_text" %}</div>

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from aldryn_apphooks_config.mixins import AppConfigMixin
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.urlresolvers import resolve
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import get_language from django.utils.translation import get_language
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
@ -14,25 +14,24 @@ from .settings import get_setting
User = get_user_model() User = get_user_model()
class BaseBlogView(ViewUrlMixin): class BaseBlogView(AppConfigMixin, ViewUrlMixin):
def get_queryset(self): def get_queryset(self):
language = get_language() language = get_language()
queryset = self.model._default_manager.all().active_translations(language_code=language) queryset = self.model._default_manager.namespace(
self.namespace
).active_translations(
language_code=language
)
if not getattr(self.request, 'toolbar', False) or not self.request.toolbar.edit_mode: if not getattr(self.request, 'toolbar', False) or not self.request.toolbar.edit_mode:
queryset = queryset.published() queryset = queryset.published()
return queryset return queryset
def render_to_response(self, context, **response_kwargs):
response_kwargs['current_app'] = resolve(self.request.path).namespace
return super(BaseBlogView, self).render_to_response(context, **response_kwargs)
class PostListView(BaseBlogView, ListView): class PostListView(BaseBlogView, ListView):
model = Post model = Post
context_object_name = 'post_list' context_object_name = 'post_list'
template_name = 'djangocms_blog/post_list.html' template_name = 'djangocms_blog/post_list.html'
paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-latest' view_url_name = 'djangocms_blog:posts-latest'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -40,6 +39,9 @@ class PostListView(BaseBlogView, ListView):
context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT') context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT')
return context return context
def get_paginate_by(self, queryset):
return self.config.paginate_by
class PostDetailView(TranslatableSlugMixin, BaseBlogView, DetailView): class PostDetailView(TranslatableSlugMixin, BaseBlogView, DetailView):
model = Post model = Post

View file

@ -48,6 +48,7 @@ setup(
'cmsplugin-filer', 'cmsplugin-filer',
'django-meta>=0.2', 'django-meta>=0.2',
'django-meta-mixin>=0.1.1', 'django-meta-mixin>=0.1.1',
'aldryn-apphooks-config',
], ],
license='BSD', license='BSD',
zip_safe=False, zip_safe=False,

View file

@ -3,11 +3,13 @@
Tests for `djangocms_blog` module. Tests for `djangocms_blog` module.
""" """
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from copy import deepcopy
from cmsplugin_filer_image.models import ThumbnailOption from cmsplugin_filer_image.models import ThumbnailOption
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.utils.translation import activate from parler.utils.context import smart_override
from djangocms_blog.cms_appconfig import BlogConfig
from djangocms_helper.base_test import BaseTestCase from djangocms_helper.base_test import BaseTestCase
from djangocms_blog.models import BlogCategory, Post from djangocms_blog.models import BlogCategory, Post
@ -31,85 +33,123 @@ class BaseTest(BaseTestCase):
{'en': {'title': 'page one', 'template': 'page.html', 'publish': True}, {'en': {'title': 'page one', 'template': 'page.html', 'publish': True},
'fr': {'title': 'page un', 'publish': True}, 'fr': {'title': 'page un', 'publish': True},
'it': {'title': 'pagina uno', 'publish': True}}, 'it': {'title': 'pagina uno', 'publish': True}},
{'en': {'title': 'page two', 'template': 'page.html', 'publish': True}, {'en': {'title': 'page two', 'template': 'page.html', 'publish': True,
'apphook': 'BlogApp', 'apphook_namespace': 'sample_app'},
'fr': {'title': 'page deux', 'publish': True}, 'fr': {'title': 'page deux', 'publish': True},
'it': {'title': 'pagina due', 'publish': True}}, 'it': {'title': 'pagina due', 'publish': True}},
{'en': {'title': 'page three', 'template': 'page.html', 'publish': True,
'apphook': 'BlogApp', 'apphook_namespace': 'sample_app2'},
'fr': {'title': 'page trois', 'publish': True},
'it': {'title': 'pagina tre', 'publish': True}},
) )
data = { _post_data = (
'it': [ {'en': {'title': 'First post', 'abstract': '<p>first line</p>',
{'title': u'Primo post', 'abstract': u'<p>prima riga</p>', 'description': 'This is the description', 'keywords': 'keyword1, keyword2',
'description': u'Questa è la descrizione', 'keywords': u'keyword1, keyword2', 'text': 'Post text', 'app_config': 'sample_app', 'publish': True},
'text': u'Testo del post'}, 'it': {'title': 'Primo post', 'abstract': '<p>prima riga</p>',
{'title': u'Secondo post', 'abstract': u'<p>prima riga del secondo post</p>', 'description': 'Questa è la descrizione', 'keywords': 'keyword1, keyword2',
'description': u'Descrizione del secondo post', 'keywords': u'keyword3, keyword4', 'text': 'Testo del post'},
'text': u'Testo del secondo post'}, },
{'title': u'Terzo post', 'abstract': u'<p>prima riga del terzo post</p>', {'en': {'title': 'Second post', 'abstract': '<p>second post first line</p>',
'description': u'Descrizione del terzo post', 'keywords': u'keyword5, keyword6', 'description': 'Second post description', 'keywords': 'keyword3, keyword4',
'text': u'Testo del terzo post'}, 'text': 'Second post text', 'app_config': 'sample_app', 'publish': False},
], 'it': {'title': 'Secondo post', 'abstract': '<p>prima riga del secondo post</p>',
'en': [ 'description': 'Descrizione del secondo post', 'keywords': 'keyword3, keyword4',
{'title': u'First post', 'abstract': u'<p>first line</p>', 'text': 'Testo del secondo post', 'app_config': 'sample_app'},
'description': u'This is the description', 'keywords': u'keyword1, keyword2', },
'text': u'Post text'}, {'en': {'title': 'Third post', 'abstract': '<p>third post first line</p>',
{'title': u'Second post', 'abstract': u'<p>second post first line</p>', 'description': 'third post description', 'keywords': 'keyword5, keyword6',
'description': u'Second post description', 'keywords': u'keyword3, keyword4', 'text': 'Third post text', 'app_config': 'sample_app', 'publish': False},
'text': u'Second post text'}, 'it': {'title': 'Terzo post', 'abstract': '<p>prima riga del terzo post</p>',
{'title': u'Third post', 'abstract': u'<p>third post first line</p>', 'description': 'Descrizione del terzo post', 'keywords': 'keyword5, keyword6',
'description': u'third post description', 'keywords': u'keyword5, keyword6', 'text': 'Testo del terzo post'},
'text': u'Third post text'} },
] {'en': {'title': 'Different appconfig', 'abstract': '<p>Different appconfig first line</p>',
} 'description': 'Different appconfig description', 'keywords': 'keyword5, keyword6',
'text': 'Different appconfig text', 'app_config': 'sample_app2', 'publish': True},
'it': {'title': 'Altro appconfig', 'abstract': '<p>prima riga del Altro appconfig</p>',
'description': 'Descrizione Altro appconfig', 'keywords': 'keyword5, keyword6',
'text': 'Testo del Altro appconfig'},
},
)
cat_data = { _categories_data = (
'it': [ {'en': {'name': 'Very loud', 'app_config': 'sample_app'},
{'name': u'Fortissimo'}, 'it': {'name': 'Fortissimo'},
{'name': u'Pianississimo'}, },
{'name': u'Mezzo'}, {'en': {'name': 'Very very silent', 'app_config': 'sample_app'},
{'name': u'Forte', 'parent_id': _get_cat_pk('it', 'Mezzo')}, 'it': {'name': 'Pianississimo'},
], },
'en': [ {'en': {'name': 'Almost', 'app_config': 'sample_app'},
{'name': u'Very loud'}, 'it': {'name': 'Mezzo'},
{'name': u'Very very silent'}, },
{'name': u'Almost'}, {'en': {'name': 'Loud', 'parent_id': _get_cat_pk('en', 'Almost'), 'app_config': 'sample_app'},
{'name': u'Loud', 'parent_id': _get_cat_pk('en', 'Almost')}, 'it': {'name': 'Forte', 'parent_id': _get_cat_pk('it', 'Mezzo')},
{'name': u'Silent', 'parent_id': _get_cat_pk('en', 'Almost')}, },
] {'en': {'name': 'Silent', 'parent_id': _get_cat_pk('en', 'Almost'), 'app_config': 'sample_app'},
} },
{'en': {'name': 'Drums', 'app_config': 'sample_app2'},
'it': {'name': 'Tamburi'},
},
{'en': {'name': 'Guitars', 'app_config': 'sample_app2'},
'it': {'name': 'Chitarre'},
},
)
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super(BaseTest, cls).setUpClass() super(BaseTest, cls).setUpClass()
cls.thumb_1 = ThumbnailOption.objects.create(
name='base', width=100, height=100, crop=True, upscale=False
)
cls.thumb_2 = ThumbnailOption.objects.create(
name='main', width=200, height=200, crop=False, upscale=False
)
cls.app_config_1 = BlogConfig.objects.create(
namespace='sample_app', app_title='app1'
)
cls.app_config_2 = BlogConfig.objects.create(
namespace='sample_app2', app_title='app2'
)
cls.app_config_1.app_data.config.paginate_by = 1
cls.app_config_1.save()
cls.app_config_2.app_data.config.paginate_by = 2
cls.app_config_2.save()
cls.app_configs = {
'sample_app': cls.app_config_1,
'sample_app2': cls.app_config_2,
}
cls.category_1 = BlogCategory.objects.create(name='category 1', app_config=cls.app_config_1)
cls.category_1.set_current_language('it', initialize=True)
cls.category_1.name = 'categoria 1'
cls.category_1.save()
cls.site_2 = Site.objects.create(domain='http://example2.com', name='example 2') cls.site_2 = Site.objects.create(domain='http://example2.com', name='example 2')
def setUp(self): def setUp(self):
activate('en')
super(BaseTest, self).setUp() super(BaseTest, self).setUp()
self.category_1 = BlogCategory.objects.create(name=u'category 1')
self.category_1.set_current_language('it', initialize=True)
self.category_1.name = u'categoria 1'
self.category_1.save()
self.thumb_1 = ThumbnailOption.objects.create(
name='base', width=100, height=100, crop=True, upscale=False
)
self.thumb_2 = ThumbnailOption.objects.create(
name='main', width=200, height=200, crop=False, upscale=False
)
self.img = self.create_filer_image_object() self.img = self.create_filer_image_object()
def tearDown(self): def tearDown(self):
for post in Post.objects.all(): Post.objects.all().delete()
post.delete()
super(BaseTest, self).tearDown() super(BaseTest, self).tearDown()
@classmethod
def tearDownClass(cls):
BlogConfig.objects.all().delete()
super(BaseTest, cls).tearDownClass()
def _get_category(self, data, category=None, lang='en'): def _get_category(self, data, category=None, lang='en'):
data = deepcopy(data)
for k, v in data.items(): for k, v in data.items():
if hasattr(v, '__call__'): if hasattr(v, '__call__'):
data[k] = v() data[k] = v()
if not category: if not category:
category = BlogCategory.objects.create(**data) with smart_override(lang):
data['app_config'] = self.app_configs[data['app_config']]
category = BlogCategory.objects.create(**data)
else: else:
category.set_current_language(lang) category.set_current_language(lang, initialize=True)
for attr, val in data.items(): for attr, val in data.items():
setattr(category, attr, val) setattr(category, attr, val)
category.save() category.save()
@ -123,15 +163,18 @@ class BaseTest(BaseTestCase):
'abstract': data['abstract'], 'abstract': data['abstract'],
'meta_description': data['description'], 'meta_description': data['description'],
'meta_keywords': data['keywords'], 'meta_keywords': data['keywords'],
'app_config': self.app_configs[data['app_config']]
} }
post = Post.objects.create(**post_data) post = Post.objects.create(**post_data)
else: else:
post.set_current_language(lang) post.create_translation(
post.title = data['title'] lang,
post.abstract = data['abstract'] title=data['title'],
post.meta_description = data['description'] abstract=data['abstract'],
post.meta_keywords = data['keywords'] meta_description=data['description'],
post.save() meta_keywords=data['keywords']
)
post = self.reload_model(post)
post.categories.add(self.category_1) post.categories.add(self.category_1)
if sites: if sites:
for site in sites: for site in sites:
@ -139,13 +182,12 @@ class BaseTest(BaseTestCase):
return post return post
def get_posts(self, sites=None): def get_posts(self, sites=None):
post1 = self._get_post(self.data['en'][0], sites=sites) posts = []
post1 = self._get_post(self.data['it'][0], post1, 'it') for post in self._post_data:
post1.publish = True post1 = self._get_post(post['en'], sites=sites)
post1.main_image = self.img post1 = self._get_post(post['it'], post=post1, lang='it')
post1.save() post1.publish = post['en']['publish']
post2 = self._get_post(self.data['en'][1], sites=sites) post1.main_image = self.img
post2 = self._get_post(self.data['it'][1], post2, 'it') post1.save()
post2.main_image = self.img posts.append(post1)
post2.save() return posts
return post1, post2

View file

@ -2,10 +2,11 @@
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
import copy import copy
from aldryn_apphooks_config.utils import get_app_instance
from django.utils.translation import activate from django.utils.translation import activate
from menus.menu_pool import menu_pool from menus.menu_pool import menu_pool
from parler.utils.context import switch_language from parler.utils.context import switch_language, smart_override
from djangocms_blog.views import CategoryEntriesView, PostDetailView from djangocms_blog.views import CategoryEntriesView, PostDetailView
@ -13,13 +14,15 @@ from . import BaseTest
class MenuTest(BaseTest): class MenuTest(BaseTest):
cats = []
def setUp(self): def setUp(self):
super(MenuTest, self).setUp() super(MenuTest, self).setUp()
self.cats = [self.category_1] self.cats = [self.category_1]
for i, cat_data in enumerate(self.cat_data['en']): for i, lang_data in enumerate(self._categories_data):
cat = self._get_category(cat_data) cat = self._get_category(lang_data['en'])
if i < len(self.cat_data['it']): if 'it' in lang_data:
cat = self._get_category(self.cat_data['it'][i], cat, 'it') cat = self._get_category(lang_data['it'], cat, 'it')
self.cats.append(cat) self.cats.append(cat)
activate('en') activate('en')
@ -32,54 +35,46 @@ class MenuTest(BaseTest):
""" """
Tests if all categories are present in the menu Tests if all categories are present in the menu
""" """
self.get_posts()
self.get_pages()
for lang in ('en', 'it'): for lang in ('en', 'it'):
request = self.get_page_request(None, self.user, request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang)
r'/%s/blog/' % lang, edit=False) with smart_override(lang):
activate(lang) nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') nodes_url = set([node.url for node in nodes])
nodes_copy = copy.deepcopy(nodes) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)])
for cat in self.cats: self.assertTrue(cats_url.issubset(nodes_url))
if not cat.has_translation(lang):
continue
with switch_language(cat, lang):
# find in node list
found = None
for node in nodes_copy:
if node.url == cat.get_absolute_url():
found = node
break
self.assertIsNotNone(found)
nodes_copy.remove(found)
self.assertEqual(node.id, cat.id)
self.assertEqual(node.title, cat.name)
# check that all categories were found in menu
self.assertEqual(len(nodes_copy), 0)
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
according to context (view object) according to context (view object)
""" """
post1, post2 = self.get_posts() posts = self.get_posts()
pages = self.get_pages()
tests = ( tests = (
# view class, view kwarg, view object, category # view class, view kwarg, view object, category
(PostDetailView, 'slug', post1, post1.categories.first()), (PostDetailView, 'slug', posts[0], posts[0].categories.first()),
(CategoryEntriesView, 'category', self.cats[2], self.cats[2]) (CategoryEntriesView, 'category', self.cats[2], self.cats[2])
) )
for view_cls, kwarg, obj, cat in tests: for view_cls, kwarg, obj, cat in tests:
request = self.get_page_request(None, self.user, r'/en/blog/', edit=False) request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url())
activate('en') with smart_override('en'):
with switch_language(obj, 'en'): with switch_language(obj, 'en'):
view_obj = view_cls() view_obj = view_cls()
view_obj.request = request view_obj.request = request
view_obj.kwargs = {kwarg: obj.slug} view_obj.namespace, view_obj.config = get_app_instance(request)
view_obj.get(request) view_obj.app_config = self.app_config_1
# check if selected menu node points to cat view_obj.kwargs = {kwarg: obj.slug}
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') view_obj.get(request)
found = False # check if selected menu node points to cat
for node in nodes: nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
if node.selected: found = False
self.assertEqual(node.url, cat.get_absolute_url()) for node in nodes:
found = True if node.selected:
break self.assertEqual(node.url, obj.get_absolute_url())
self.assertTrue(found) found = True
break
self.assertTrue(found)

View file

@ -25,24 +25,41 @@ from . import BaseTest
class AdminTest(BaseTest): class AdminTest(BaseTest):
def setUp(self):
super(AdminTest, self).setUp()
admin.autodiscover()
def test_admin_fieldsets(self): def test_admin_fieldsets(self):
request = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=False)
post_admin = admin.site._registry[Post] post_admin = admin.site._registry[Post]
request = self.get_page_request('/', self.user_staff, r'/en/blog/?app_config=%s' % self.app_config_1.pk, edit=False)
with self.settings(BLOG_USE_PLACEHOLDER=True): # Use placeholder
fsets = post_admin.get_fieldsets(request) self.app_config_1.app_data.config.use_placeholder = True
self.assertFalse('post_text' in fsets[0][1]['fields']) self.app_config_1.save()
fsets = post_admin.get_fieldsets(request)
self.assertFalse('post_text' in fsets[0][1]['fields'])
with self.settings(BLOG_USE_PLACEHOLDER=False): self.app_config_1.app_data.config.use_placeholder = False
fsets = post_admin.get_fieldsets(request) self.app_config_1.save()
self.assertTrue('post_text' in fsets[0][1]['fields']) fsets = post_admin.get_fieldsets(request)
self.assertTrue('post_text' in fsets[0][1]['fields'])
with self.settings(BLOG_USE_ABSTRACT=True): self.app_config_1.app_data.config.use_placeholder = True
fsets = post_admin.get_fieldsets(request) self.app_config_1.save()
self.assertTrue('abstract' in fsets[0][1]['fields'])
with self.settings(BLOG_USE_ABSTRACT=False): # Use abstract
fsets = post_admin.get_fieldsets(request) self.app_config_1.app_data.config.use_abstract = True
self.assertFalse('abstract' in fsets[0][1]['fields']) self.app_config_1.save()
fsets = post_admin.get_fieldsets(request)
self.assertTrue('abstract' in fsets[0][1]['fields'])
self.app_config_1.app_data.config.use_abstract = False
self.app_config_1.save()
fsets = post_admin.get_fieldsets(request)
self.assertFalse('abstract' in fsets[0][1]['fields'])
self.app_config_1.app_data.config.use_abstract = True
self.app_config_1.save()
with self.settings(BLOG_MULTISITE=True): with self.settings(BLOG_MULTISITE=True):
fsets = post_admin.get_fieldsets(request) fsets = post_admin.get_fieldsets(request)
@ -51,49 +68,55 @@ class AdminTest(BaseTest):
fsets = post_admin.get_fieldsets(request) fsets = post_admin.get_fieldsets(request)
self.assertFalse('sites' in fsets[1][1]['fields'][0]) self.assertFalse('sites' in fsets[1][1]['fields'][0])
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False) request = self.get_page_request('/', self.user, r'/en/blog/?app_config=%s' % self.app_config_1.pk, edit=False)
fsets = post_admin.get_fieldsets(request) fsets = post_admin.get_fieldsets(request)
self.assertTrue('author' in fsets[1][1]['fields'][0]) self.assertTrue('author' in fsets[1][1]['fields'][0])
def test_admin_auto_author(self): def test_admin_auto_author(self):
page1, page2 = self.get_pages() pages = self.get_pages()
data = deepcopy(self.data['en'][0]) data = deepcopy(self._post_data[0]['en'])
with self.login_user_context(self.user): with self.login_user_context(self.user):
with self.settings(BLOG_AUTHOR_DEFAULT=True): self.app_config_1.app_data.config.set_author = True
data['date_published_0'] = now().strftime('%Y-%m-%d') self.app_config_1.save()
data['date_published_1'] = now().strftime('%H:%M:%S') data['date_published_0'] = now().strftime('%Y-%m-%d')
data['categories'] = self.category_1.pk data['date_published_1'] = now().strftime('%H:%M:%S')
request = self.post_request(page1, 'en', user=self.user, data=data, path='/en/?edit_fields=post_text') data['categories'] = self.category_1.pk
msg_mid = MessageMiddleware() data['app_config'] = self.app_config_1.pk
msg_mid.process_request(request) request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk)
post_admin = admin.site._registry[Post] msg_mid = MessageMiddleware()
response = post_admin.add_view(request) msg_mid.process_request(request)
self.assertEqual(response.status_code, 302) post_admin = admin.site._registry[Post]
self.assertEqual(Post.objects.count(), 1) response = post_admin.add_view(request)
self.assertEqual(Post.objects.get(translations__slug='first-post').author_id, self.assertEqual(response.status_code, 302)
request.user.pk) self.assertEqual(Post.objects.count(), 1)
self.assertEqual(Post.objects.get(translations__slug='first-post').author_id, request.user.pk)
with self.settings(BLOG_AUTHOR_DEFAULT=False): self.app_config_1.app_data.config.set_author = False
data = deepcopy(self.data['en'][1]) self.app_config_1.save()
data['date_published_0'] = now().strftime('%Y-%m-%d') data = deepcopy(self._post_data[1]['en'])
data['date_published_1'] = now().strftime('%H:%M:%S') data['date_published_0'] = now().strftime('%Y-%m-%d')
data['categories'] = self.category_1.pk data['date_published_1'] = now().strftime('%H:%M:%S')
request = self.post_request(page1, 'en', user=self.user, data=data, path='/en/?edit_fields=post_text') data['categories'] = self.category_1.pk
msg_mid = MessageMiddleware() data['app_config'] = self.app_config_1.pk
msg_mid.process_request(request) request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk)
post_admin = admin.site._registry[Post] msg_mid = MessageMiddleware()
response = post_admin.add_view(request) msg_mid.process_request(request)
self.assertEqual(response.status_code, 302) post_admin = admin.site._registry[Post]
self.assertEqual(Post.objects.count(), 2) response = post_admin.add_view(request)
self.assertEqual(Post.objects.get(translations__slug='second-post').author_id, None) self.assertEqual(response.status_code, 302)
self.assertEqual(Post.objects.count(), 2)
self.assertEqual(Post.objects.get(translations__slug='second-post').author_id, None)
with self.settings(BLOG_AUTHOR_DEFAULT='staff'): with self.settings(BLOG_AUTHOR_DEFAULT='staff'):
data = deepcopy(self.data['en'][2]) self.app_config_1.app_data.config.set_author = True
self.app_config_1.save()
data = deepcopy(self._post_data[2]['en'])
data['date_published_0'] = now().strftime('%Y-%m-%d') data['date_published_0'] = now().strftime('%Y-%m-%d')
data['date_published_1'] = now().strftime('%H:%M:%S') data['date_published_1'] = now().strftime('%H:%M:%S')
data['categories'] = self.category_1.pk data['categories'] = self.category_1.pk
request = self.post_request(page1, 'en', user=self.user, data=data, path='/en/?edit_fields=post_text') data['app_config'] = self.app_config_1.pk
request = self.post_request(pages[0], 'en', user=self.user, data=data, path=r'/en/blog/?app_config=%s' % self.app_config_1.pk)
msg_mid = MessageMiddleware() msg_mid = MessageMiddleware()
msg_mid.process_request(request) msg_mid.process_request(request)
post_admin = admin.site._registry[Post] post_admin = admin.site._registry[Post]
@ -103,17 +126,18 @@ class AdminTest(BaseTest):
self.assertEqual(Post.objects.get(translations__slug='third-post').author.username, 'staff') self.assertEqual(Post.objects.get(translations__slug='third-post').author.username, 'staff')
def test_admin_post_text(self): def test_admin_post_text(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post = self._get_post(self.data['en'][0]) post = self._get_post(self._post_data[0]['en'])
with self.login_user_context(self.user): with self.login_user_context(self.user):
with self.settings(BLOG_USE_PLACEHOLDER=False): with self.settings(BLOG_USE_PLACEHOLDER=False):
data = {'post_text': 'ehi text'} data = {'post_text': 'ehi text', 'title': 'some title'}
request = self.post_request(page1, 'en', user=self.user, data=data, path='/en/?edit_fields=post_text') request = self.post_request(pages[0], 'en', user=self.user, data=data, path='/en/?edit_fields=post_text')
msg_mid = MessageMiddleware() msg_mid = MessageMiddleware()
msg_mid.process_request(request) msg_mid.process_request(request)
post_admin = admin.site._registry[Post] post_admin = admin.site._registry[Post]
response = post_admin.edit_field(request, post.pk, 'en') response = post_admin.edit_field(request, post.pk, 'en')
#print(response.content.decode('utf-8'))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
modified_post = Post.objects.language('en').get(pk=post.pk) modified_post = Post.objects.language('en').get(pk=post.pk)
self.assertEqual(modified_post.safe_translation_getter('post_text'), data['post_text']) self.assertEqual(modified_post.safe_translation_getter('post_text'), data['post_text'])
@ -122,8 +146,8 @@ class AdminTest(BaseTest):
class ModelsTest(BaseTest): class ModelsTest(BaseTest):
def test_model_attributes(self): def test_model_attributes(self):
post = self._get_post(self.data['en'][0]) post = self._get_post(self._post_data[0]['en'])
post = self._get_post(self.data['it'][0], post, 'it') post = self._get_post(self._post_data[0]['it'], post, 'it')
post.main_image = self.img post.main_image = self.img
post.save() post.save()
post.set_current_language('en') post.set_current_language('en')
@ -186,8 +210,8 @@ class ModelsTest(BaseTest):
self.assertEqual(post.get_title(), 'meta title') self.assertEqual(post.get_title(), 'meta title')
def test_manager(self): def test_manager(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
post2 = self._get_post(self.data['en'][1]) post2 = self._get_post(self._post_data[1]['en'])
# default queryset, published and unpublished posts # default queryset, published and unpublished posts
months = Post.objects.get_months() months = Post.objects.get_months()
@ -222,7 +246,7 @@ class ModelsTest(BaseTest):
self.assertEqual(len(Post.objects.archived()), 1) self.assertEqual(len(Post.objects.archived()), 1)
# counting with language fallback enabled # counting with language fallback enabled
self._get_post(self.data['it'][0], 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')), 2)
# No fallback # No fallback
@ -235,8 +259,8 @@ class ModelsTest(BaseTest):
parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]['hide_untranslated'] = False parler.appsettings.PARLER_LANGUAGES[Site.objects.get_current().pk][index]['hide_untranslated'] = False
def test_tag_cloud(self): def test_tag_cloud(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
post2 = self._get_post(self.data['en'][1]) post2 = self._get_post(self._post_data[1]['en'])
post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
post1.save() post1.save()
post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
@ -270,14 +294,14 @@ class ModelsTest(BaseTest):
self.assertEqual(set(Post.objects.tag_cloud(published=False)), set(tags)) self.assertEqual(set(Post.objects.tag_cloud(published=False)), set(tags))
def test_plugin_latest(self): def test_plugin_latest(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
self._get_post(self.data['en'][1]) self._get_post(self._post_data[1]['en'])
post1.tags.add('tag 1') post1.tags.add('tag 1')
post1.save() post1.save()
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') 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
@ -292,11 +316,11 @@ class ModelsTest(BaseTest):
self.assertEqual(len(plugin.get_posts(request)), 1) self.assertEqual(len(plugin.get_posts(request)), 1)
def test_copy_plugin_latest(self): def test_copy_plugin_latest(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
post2 = self._get_post(self.data['en'][1]) 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') 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:
@ -309,10 +333,10 @@ class ModelsTest(BaseTest):
self.assertEqual(set(new[0].tags.all()), set(plugin.tags.all())) self.assertEqual(set(new[0].tags.all()), set(plugin.tags.all()))
def test_plugin_author(self): def test_plugin_author(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
post2 = self._get_post(self.data['en'][1]) 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') 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)
@ -328,9 +352,9 @@ class ModelsTest(BaseTest):
self.assertEqual(plugin.get_authors()[0].count, 2) self.assertEqual(plugin.get_authors()[0].count, 2)
def test_copy_plugin_author(self): def test_copy_plugin_author(self):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self._post_data[0]['en'])
post2 = self._get_post(self.data['en'][1]) post2 = self._get_post(self._post_data[1]['en'])
plugin = add_plugin(post1.content, 'BlogAuthorPostsPlugin', language='en') 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'))
@ -342,9 +366,9 @@ class ModelsTest(BaseTest):
def test_multisite(self): def test_multisite(self):
with override('en'): with override('en'):
post1 = self._get_post(self.data['en'][0], sites=(self.site_1,)) post1 = self._get_post(self._post_data[0]['en'], sites=(self.site_1,))
post2 = self._get_post(self.data['en'][1], sites=(self.site_2,)) post2 = self._get_post(self._post_data[1]['en'], sites=(self.site_2,))
post3 = self._get_post(self.data['en'][2], sites=(self.site_2, self.site_1)) post3 = self._get_post(self._post_data[2]['en'], sites=(self.site_2, self.site_1))
self.assertEqual(len(Post.objects.all()), 3) self.assertEqual(len(Post.objects.all()), 3)
with self.settings(**{'SITE_ID': self.site_1.pk}): with self.settings(**{'SITE_ID': self.site_1.pk}):

View file

@ -16,73 +16,70 @@ from . import BaseTest
class PluginTest(BaseTest): class PluginTest(BaseTest):
def test_plugin_latest(self): def test_plugin_latest(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1 = self._get_post(self.data['en'][0]) posts = self.get_posts()
post2 = self._get_post(self.data['en'][1]) posts[0].tags.add('tag 1')
post1.tags.add('tag 1') posts[0].publish = True
post1.publish = True posts[0].save()
post1.save() ph = pages[0].placeholders.get(slot='content')
ph = page1.placeholders.get(slot='content')
plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en') 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)
context = self.get_plugin_context(page1, '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)
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(post1.get_absolute_url()) > -1) self.assertTrue(rendered.find(posts[0].get_absolute_url()) > -1)
category_2 = BlogCategory.objects.create(name=u'category 2') category_2 = BlogCategory.objects.create(name='category 2', app_config=self.app_config_1)
category_2.set_current_language('it', initialize=True) category_2.set_current_language('it', initialize=True)
category_2.name = u'categoria 2' category_2.name = 'categoria 2'
category_2.save() category_2.save()
category_2.set_current_language('en') category_2.set_current_language('en')
post2.categories.add(category_2) posts[1].categories.add(category_2)
plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en') 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(page1, '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)
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(post2.get_absolute_url()) > -1) self.assertTrue(rendered.find(posts[1].get_absolute_url()) > -1)
def test_plugin_authors(self): def test_plugin_authors(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1 = self._get_post(self.data['en'][0]) posts = self.get_posts()
post2 = self._get_post(self.data['en'][1]) posts[0].publish = True
post1.publish = True posts[0].save()
post1.save() posts[1].publish = True
post2.publish = True posts[1].save()
post2.save() ph = pages[0].placeholders.get(slot='content')
ph = page1.placeholders.get(slot='content') plugin = add_plugin(ph, 'BlogAuthorPostsPlugin', language='en', app_config=self.app_config_1)
plugin = add_plugin(ph, 'BlogAuthorPostsPlugin', language='en')
plugin.authors.add(self.user) plugin.authors.add(self.user)
context = self.get_plugin_context(page1, '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)
self.assertTrue(rendered.find(reverse('djangocms_blog:posts-author', kwargs={'username': self.user.get_username()})) > -1) self.assertTrue(rendered.find(reverse('djangocms_blog:posts-author', kwargs={'username': self.user.get_username()})) > -1)
self.assertTrue(rendered.find('2 articles') > -1) self.assertTrue(rendered.find('2 articles') > -1)
def test_plugin_tags(self): def test_plugin_tags(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1 = self._get_post(self.data['en'][0]) posts = self.get_posts()
post2 = self._get_post(self.data['en'][1]) posts[0].tags.add('tag 1', 'tag 2', 'test tag')
post1.tags.add('tag 1', 'tag 2', 'test tag') posts[0].publish = True
post1.publish = True posts[0].save()
post1.save() posts[1].tags.add('test tag', 'another tag')
post2.tags.add('test tag', 'another tag') posts[1].publish = True
post2.publish = True posts[1].save()
post2.save() ph = pages[0].placeholders.get(slot='content')
ph = page1.placeholders.get(slot='content') plugin = add_plugin(ph, 'BlogTagsPlugin', language='en', app_config=self.app_config_1)
plugin = add_plugin(ph, 'BlogTagsPlugin', language='en') context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
context = self.get_plugin_context(page1, '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)
@ -94,38 +91,38 @@ class PluginTest(BaseTest):
self.assertEqual(len(rx.findall(rendered)), 1) self.assertEqual(len(rx.findall(rendered)), 1)
def test_blog_category_plugin(self): def test_blog_category_plugin(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1, post2 = self.get_posts() posts = self.get_posts()
post1.publish = True posts[0].publish = True
post1.save() posts[0].save()
post2.publish = True posts[1].publish = True
post2.save() posts[1].save()
ph = page1.placeholders.get(slot='content') ph = pages[0].placeholders.get(slot='content')
plugin = add_plugin(ph, 'BlogCategoryPlugin', language='en') plugin = add_plugin(ph, 'BlogCategoryPlugin', language='en', app_config=self.app_config_1)
plugin_class = plugin.get_plugin_class_instance() plugin_class = plugin.get_plugin_class_instance()
context = self.get_plugin_context(page1, 'en', plugin, edit=True) context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
context = plugin_class.render(context, plugin, ph) context = plugin_class.render(context, plugin, ph)
self.assertTrue(context['categories']) self.assertTrue(context['categories'])
self.assertEqual(list(context['categories']), [self.category_1]) self.assertEqual(list(context['categories']), [self.category_1])
def test_blog_archive_plugin(self): def test_blog_archive_plugin(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1, post2 = self.get_posts() posts = self.get_posts()
post1.publish = True posts[0].publish = True
post1.save() posts[0].save()
post2.publish = True posts[1].publish = True
post2.save() posts[1].save()
ph = page1.placeholders.get(slot='content') ph = pages[0].placeholders.get(slot='content')
plugin = add_plugin(ph, 'BlogArchivePlugin', language='en') plugin = add_plugin(ph, 'BlogArchivePlugin', language='en', app_config=self.app_config_1)
plugin_class = plugin.get_plugin_class_instance() plugin_class = plugin.get_plugin_class_instance()
context = self.get_plugin_context(page1, 'en', plugin, edit=True) context = self.get_plugin_context(pages[0], 'en', plugin, edit=True)
context = plugin_class.render(context, plugin, ph) context = plugin_class.render(context, plugin, ph)
self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date())
self.assertEqual(context['dates'][0]['count'], 2) self.assertEqual(context['dates'][0]['count'], 2)
post2.publish = False posts[1].publish = False
post2.save() posts[1].save()
context = plugin_class.render(context, plugin, ph) context = plugin_class.render(context, plugin, ph)
self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) self.assertEqual(context['dates'][0]['date'].date(), now().replace(year=now().year, month=now().month, day=1).date())
self.assertEqual(context['dates'][0]['count'], 1) self.assertEqual(context['dates'][0]['count'], 1)

View file

@ -16,13 +16,13 @@ class ToolbarTest(BaseTest):
Test that Blog toolbar is present and contains all items Test that Blog toolbar is present and contains all items
""" """
from cms.toolbar.toolbar import CMSToolbar from cms.toolbar.toolbar import CMSToolbar
post = self._get_post(self.data['en'][0]) posts = self.get_posts()
page1, page2 = self.get_pages() pages = self.get_pages()
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True) request = self.get_page_request(pages[0], self.user, r'/en/blog/', edit=True)
setattr(request, BLOG_CURRENT_POST_IDENTIFIER, post) setattr(request, BLOG_CURRENT_POST_IDENTIFIER, posts[0])
toolbar = CMSToolbar(request) toolbar = CMSToolbar(request)
toolbar.get_left_items() toolbar.get_left_items()
blog_menu = toolbar.menus['djangocms_blog'] blog_menu = toolbar.menus['djangocms_blog']
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1) self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1)
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1) self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1)
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(post.pk,)))), 1) self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(posts[0].pk,)))), 1)

View file

@ -21,51 +21,53 @@ from . import BaseTest
class ViewTest(BaseTest): class ViewTest(BaseTest):
def test_post_list_view(self): def test_post_list_view(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False) request = self.get_page_request(pages[0], AnonymousUser(), r'/en/blog/', edit=False)
with smart_override('en'): with smart_override('en'):
view_obj = PostListView() view_obj = PostListView()
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
self.assertEqual(list(view_obj.get_queryset()), [post1]) self.assertEqual(list(view_obj.get_queryset()), [posts[0]])
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False) request = self.get_page_request(pages[1], self.user, edit=False)
view_obj.request = request view_obj.request = request
view_obj.kwargs = {} view_obj.kwargs = {}
qs = view_obj.get_queryset() qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 1) self.assertEqual(qs.count(), 1)
self.assertEqual(set(qs), set([post1])) self.assertEqual(set(qs), set([posts[0]]))
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True) request = self.get_page_request(pages[1], self.user, edit=True)
view_obj.request = request view_obj.request = request
self.assertEqual(set(view_obj.get_queryset()), set([post1, post2])) self.assertEqual(set(view_obj.get_queryset()), set([posts[0], posts[1], posts[2]]))
view_obj.kwargs = {} view_obj.kwargs = {}
view_obj.object_list = view_obj.get_queryset() view_obj.object_list = view_obj.get_queryset()
view_obj.paginate_by = 1 view_obj.paginate_by = 1
context = view_obj.get_context_data(object_list=view_obj.object_list) context = view_obj.get_context_data(object_list=view_obj.object_list)
self.assertTrue(context['is_paginated']) self.assertTrue(context['is_paginated'])
self.assertEqual(list(context['post_list']), [post2]) self.assertEqual(list(context['post_list']), [posts[2]])
self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['paginator'].count, 3)
self.assertEqual(context['post_list'][0].title, 'Second post') self.assertEqual(context['post_list'][0].title, 'Third post')
response = view_obj.render_to_response(context) response = view_obj.render_to_response(context)
self.assertContains(response, context['post_list'][0].get_absolute_url()) self.assertContains(response, context['post_list'][0].get_absolute_url())
with smart_override('it'): with smart_override('it'):
request = self.get_page_request(page1, self.user, r'/it/blog/', lang='it', edit=True) request = self.get_page_request(pages[1], self.user, lang='it', edit=True)
view_obj.request = request view_obj.request = request
view_obj.object_list = view_obj.get_queryset() view_obj.object_list = view_obj.get_queryset()
context = view_obj.get_context_data(object_list=view_obj.object_list) context = view_obj.get_context_data(object_list=view_obj.object_list)
self.assertEqual(context['post_list'][0].title, 'Secondo post') self.assertEqual(context['post_list'][0].title, 'Terzo post')
response = view_obj.render_to_response(context) response = view_obj.render_to_response(context)
self.assertContains(response, context['post_list'][0].get_absolute_url()) self.assertContains(response, context['post_list'][0].get_absolute_url())
def test_post_list_view_fallback(self): def test_post_list_view_fallback(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
PARLER_FALLBACK = { PARLER_FALLBACK = {
1: ( 1: (
@ -81,89 +83,103 @@ class ViewTest(BaseTest):
with smart_override('fr'): with smart_override('fr'):
view_obj = PostListView() view_obj = PostListView()
request = self.get_page_request(page1, self.user, r'/fr/blog/', lang='fr', edit=True) request = self.get_page_request(pages[0], self.user, r'/fr/blog/', lang='fr', edit=True)
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {} view_obj.kwargs = {}
view_obj.object_list = view_obj.get_queryset() view_obj.object_list = view_obj.get_queryset()
view_obj.get_context_data(object_list=view_obj.object_list) view_obj.get_context_data(object_list=view_obj.object_list)
self.assertEqual(view_obj.get_queryset().count(), 2) self.assertEqual(view_obj.get_queryset().count(), 3)
PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK)
with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK): with override_parler_settings(PARLER_LANGUAGES=PARLER_FALLBACK):
view_obj = PostListView() view_obj = PostListView()
request = self.get_page_request(page1, self.user, r'/fr/blog/', lang='fr', edit=True) request = self.get_page_request(pages[0], self.user, r'/fr/blog/', lang='fr', edit=True)
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {} view_obj.kwargs = {}
view_obj.object_list = view_obj.get_queryset() view_obj.object_list = view_obj.get_queryset()
view_obj.get_context_data(object_list=view_obj.object_list) view_obj.get_context_data(object_list=view_obj.object_list)
self.assertEqual(view_obj.get_queryset().count(), 0) self.assertEqual(view_obj.get_queryset().count(), 0)
def test_post_detail_view(self): def test_post_detail_view(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
with smart_override('en'): with smart_override('en'):
with switch_language(post1, 'en'): with switch_language(posts[0], 'en'):
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False) request = self.get_page_request(pages[0], AnonymousUser(), r'/en/blog/', edit=False)
view_obj = PostDetailView() view_obj = PostDetailView()
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
with self.assertRaises(Http404): with self.assertRaises(Http404):
view_obj.kwargs = {'slug': 'not-existing'} view_obj.kwargs = {'slug': 'not-existing'}
post_obj = view_obj.get_object() post_obj = view_obj.get_object()
view_obj.kwargs = {'slug': post1.slug} view_obj.kwargs = {'slug': posts[0].slug}
post_obj = view_obj.get_object() post_obj = view_obj.get_object()
self.assertEqual(post_obj, post1) self.assertEqual(post_obj, posts[0])
self.assertEqual(post_obj.language_code, 'en') self.assertEqual(post_obj.language_code, 'en')
with smart_override('it'): with smart_override('it'):
with switch_language(post1, 'it'): with switch_language(posts[0], 'it'):
request = self.get_page_request(page1, AnonymousUser(), r'/it/blog/', lang='it', edit=False) request = self.get_page_request(pages[0], AnonymousUser(), r'/it/blog/', lang='it', edit=False)
view_obj = PostDetailView()
view_obj.request = request view_obj.request = request
view_obj.kwargs = {'slug': post1.slug} view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {'slug': posts[0].slug}
post_obj = view_obj.get_object() post_obj = view_obj.get_object()
self.assertEqual(post_obj, post1) self.assertEqual(post_obj, posts[0])
self.assertEqual(post_obj.language_code, 'it') self.assertEqual(post_obj.language_code, 'it')
view_obj.object = post_obj view_obj.object = post_obj
context = view_obj.get_context_data() context = view_obj.get_context_data()
self.assertEqual(context['post'], post1) self.assertEqual(context['post'], posts[0])
self.assertEqual(context['post'].language_code, 'it') self.assertEqual(context['post'].language_code, 'it')
self.assertTrue(context['meta']) self.assertTrue(context['meta'])
def test_post_archive_view(self): def test_post_archive_view(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
with smart_override('en'): with smart_override('en'):
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False) request = self.get_page_request(pages[0], AnonymousUser(), r'/en/blog/', edit=False)
view_obj = PostArchiveView() view_obj = PostArchiveView()
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {'year': now().year, 'month': now().month} view_obj.kwargs = {'year': now().year, 'month': now().month}
# One post only, anonymous request # One post only, anonymous request
qs = view_obj.get_queryset() qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 1) self.assertEqual(qs.count(), 1)
self.assertEqual(list(qs), [post1]) self.assertEqual(list(qs), [posts[0]])
view_obj.object_list = qs view_obj.object_list = qs
context = view_obj.get_context_data(object_list=view_obj.object_list) context = view_obj.get_context_data(object_list=view_obj.object_list)
self.assertEqual(context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) self.assertEqual(context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date())
def test_category_entries_view(self): def test_category_entries_view(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
with smart_override('en'): with smart_override('en'):
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True) request = self.get_page_request(pages[0], self.user, r'/en/blog/', edit=True)
view_obj = CategoryEntriesView() view_obj = CategoryEntriesView()
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {'category': 'category-1'} view_obj.kwargs = {'category': 'category-1'}
qs = view_obj.get_queryset() qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 2) self.assertEqual(qs.count(), 3)
self.assertEqual(set(qs), set([post1, post2])) self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]]))
view_obj.paginate_by = 1 view_obj.paginate_by = 1
view_obj.object_list = qs view_obj.object_list = qs
@ -171,22 +187,29 @@ class ViewTest(BaseTest):
self.assertTrue(context['category']) self.assertTrue(context['category'])
self.assertEqual(context['category'], self.category_1) self.assertEqual(context['category'], self.category_1)
self.assertTrue(context['is_paginated']) self.assertTrue(context['is_paginated'])
self.assertEqual(list(context['post_list']), [post2]) self.assertEqual(list(context['post_list']), [posts[2]])
self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['paginator'].count, 3)
self.assertEqual(context['post_list'][0].title, 'Second post') self.assertEqual(context['post_list'][0].title, 'Third post')
request = self.get_page_request(pages[1], self.user, edit=False)
view_obj.request = request
qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 1)
def test_author_entries_view(self): def test_author_entries_view(self):
page1, page2 = self.get_pages() posts = self.get_posts()
post1, post2 = self.get_posts() pages = self.get_pages()
with smart_override('en'): with smart_override('en'):
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True) request = self.get_page_request(pages[1], self.user, edit=True)
view_obj = AuthorEntriesView() view_obj = AuthorEntriesView()
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.request = request view_obj.request = request
view_obj.kwargs = {'username': self.user.get_username()} view_obj.kwargs = {'username': self.user.get_username()}
qs = view_obj.get_queryset() qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 2) self.assertEqual(qs.count(), 3)
self.assertEqual(set(qs), set([post1, post2])) self.assertEqual(set(qs), set([posts[0], posts[1], posts[2]]))
view_obj.paginate_by = 1 view_obj.paginate_by = 1
view_obj.object_list = qs view_obj.object_list = qs
@ -194,74 +217,87 @@ class ViewTest(BaseTest):
self.assertTrue(context['author']) self.assertTrue(context['author'])
self.assertEqual(context['author'], self.user) self.assertEqual(context['author'], self.user)
self.assertTrue(context['is_paginated']) self.assertTrue(context['is_paginated'])
self.assertEqual(list(context['post_list']), [post2]) self.assertEqual(list(context['post_list']), [posts[2]])
self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['paginator'].count, 3)
self.assertEqual(context['post_list'][0].title, 'Second post') self.assertEqual(context['post_list'][0].title, 'Third post')
request = self.get_page_request(pages[1], self.user, edit=False)
view_obj.request = request
qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 1)
def test_taggedlist_view(self): def test_taggedlist_view(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1, post2 = self.get_posts() posts = self.get_posts()
post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
post1.save() posts[0].save()
post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
post2.save() posts[1].save()
with smart_override('en'): with smart_override('en'):
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True) request = self.get_page_request(pages[1], self.user, edit=True)
view_obj = TaggedListView() view_obj = TaggedListView()
view_obj.request = request view_obj.request = request
view_obj.namespace = self.app_config_1.namespace
view_obj.config = self.app_config_1
view_obj.kwargs = {'tag': 'tag-2'} view_obj.kwargs = {'tag': 'tag-2'}
qs = view_obj.get_queryset() qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 2) self.assertEqual(qs.count(), 2)
self.assertEqual(set(qs), set([post1, post2])) self.assertEqual(set(qs), set([posts[0], posts[1]]))
view_obj.paginate_by = 1 view_obj.paginate_by = 1
view_obj.object_list = qs view_obj.object_list = qs
context = view_obj.get_context_data(object_list=view_obj.object_list) context = view_obj.get_context_data(object_list=view_obj.object_list)
self.assertTrue(context['tagged_entries'], 'tag-2') self.assertTrue(context['tagged_entries'], 'tag-2')
self.assertTrue(context['is_paginated']) self.assertTrue(context['is_paginated'])
self.assertEqual(list(context['post_list']), [post2]) self.assertEqual(list(context['post_list']), [posts[1]])
self.assertEqual(context['paginator'].count, 2) self.assertEqual(context['paginator'].count, 2)
self.assertEqual(context['post_list'][0].title, 'Second post') self.assertEqual(context['post_list'][0].title, 'Second post')
def test_feed(self): def test_feed(self):
page1, page2 = self.get_pages() pages = self.get_pages()
post1, post2 = self.get_posts() posts = self.get_posts()
post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
post1.save() posts[0].save()
post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
post2.save() posts[1].save()
post1.set_current_language('en') posts[0].set_current_language('en')
feed = LatestEntriesFeed() feed = LatestEntriesFeed()
self.assertEqual(list(feed.items()), [post1]) feed.namespace = self.app_config_1.namespace
request = self.get_page_request(page1, self.user, r'/en/blog/', lang='en', edit=False) feed.config = self.app_config_1
self.assertEqual(list(feed.items()), [posts[0]])
request = self.get_page_request(pages[1], self.user, lang='en', edit=False)
xml = feed(request) xml = feed(request)
self.assertContains(xml, post1.get_absolute_url()) self.assertContains(xml, posts[0].get_absolute_url())
self.assertContains(xml, 'Blog articles on example.com') self.assertContains(xml, 'Blog articles on example.com')
with smart_override('it'): with smart_override('it'):
with switch_language(post1, 'it'): with switch_language(posts[0], 'it'):
feed = LatestEntriesFeed() feed = LatestEntriesFeed()
self.assertEqual(list(feed.items()), [post1]) feed.namespace = self.app_config_1.namespace
request = self.get_page_request(page1, self.user, r'/it/blog/', lang='it', edit=False) feed.config = self.app_config_1
self.assertEqual(list(feed.items()), [posts[0]])
request = self.get_page_request(pages[1], self.user, lang='en', edit=False)
xml = feed(request) xml = feed(request)
self.assertContains(xml, post1.get_absolute_url()) self.assertContains(xml, posts[0].get_absolute_url())
self.assertContains(xml, 'Articoli del blog su example.com') self.assertContains(xml, 'Articoli del blog su example.com')
feed = TagFeed() feed = TagFeed()
self.assertEqual(list(feed.items('tag-2')), [post1]) feed.namespace = self.app_config_1.namespace
feed.config = self.app_config_1
self.assertEqual(list(feed.items('tag-2')), [posts[0]])
def test_sitemap(self): def test_sitemap(self):
post1, post2 = self.get_posts() posts = self.get_posts()
post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
post1.save() posts[0].save()
post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
post2.publish = True posts[1].publish = True
post2.save() posts[1].save()
post1.set_current_language('en') posts[0].set_current_language('en')
sitemap = BlogSitemap() sitemap = BlogSitemap()
self.assertEqual(sitemap.items().count(), 2) self.assertEqual(sitemap.items().count(), 3)
for item in sitemap.items(): for item in sitemap.items():
self.assertTrue(sitemap.lastmod(item).date(), now().today()) self.assertTrue(sitemap.lastmod(item).date(), now().today())