Add support for configurable menu structure
This commit is contained in:
parent
8b97c9256e
commit
c5e0227565
3 changed files with 140 additions and 35 deletions
|
|
@ -9,7 +9,7 @@ from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from parler.models import TranslatableModel, TranslatedFields
|
from parler.models import TranslatableModel, TranslatedFields
|
||||||
|
|
||||||
from .settings import get_setting
|
from .settings import MENU_TYPE_COMPLETE, get_setting
|
||||||
|
|
||||||
|
|
||||||
class BlogConfig(TranslatableModel, AppHookConfig):
|
class BlogConfig(TranslatableModel, AppHookConfig):
|
||||||
|
|
@ -54,41 +54,57 @@ class BlogConfigForm(AppDataForm):
|
||||||
label=_('Template prefix'), required=False, initial='',
|
label=_('Template prefix'), required=False, initial='',
|
||||||
help_text=_('Alternative directory to load the blog templates from')
|
help_text=_('Alternative directory to load the blog templates from')
|
||||||
)
|
)
|
||||||
|
menu_structure = forms.ChoiceField(
|
||||||
|
label=_('Menu structure'), required=True,
|
||||||
|
choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE,
|
||||||
|
help_text=_('Structure of the django CMS menu')
|
||||||
|
)
|
||||||
object_type = forms.ChoiceField(
|
object_type = forms.ChoiceField(
|
||||||
label=_('Object type'), required=False,
|
label=_('Object type'), required=False,
|
||||||
choices=get_setting('TYPES'), initial=get_setting('TYPE')
|
choices=get_setting('TYPES'), initial=get_setting('TYPE')
|
||||||
)
|
)
|
||||||
og_type = forms.ChoiceField(
|
og_type = forms.ChoiceField(
|
||||||
label=_('Facebook type'), required=False,
|
label=_('Facebook type'), required=False,
|
||||||
choices=get_setting('FB_TYPES'), initial=get_setting('FB_TYPES')[0][0]
|
choices=get_setting('FB_TYPES'), initial=get_setting('FB_TYPE')
|
||||||
)
|
)
|
||||||
og_app_id = forms.CharField(
|
og_app_id = forms.CharField(
|
||||||
max_length=200, label=_('Facebook application ID'), required=False,
|
max_length=200, label=_('Facebook application ID'), required=False,
|
||||||
|
initial=get_setting('FB_PROFILE_ID')
|
||||||
)
|
)
|
||||||
og_profile_id = forms.CharField(
|
og_profile_id = forms.CharField(
|
||||||
max_length=200, label=_('Facebook profile ID'), required=False,
|
max_length=200, label=_('Facebook profile ID'), required=False,
|
||||||
|
initial=get_setting('FB_PROFILE_ID')
|
||||||
)
|
)
|
||||||
og_publisher = forms.CharField(
|
og_publisher = forms.CharField(
|
||||||
max_length=200, label=_('Facebook page URL'), required=False
|
max_length=200, label=_('Facebook page URL'), required=False,
|
||||||
|
initial=get_setting('FB_PUBLISHER')
|
||||||
)
|
)
|
||||||
og_author_url = forms.CharField(
|
og_author_url = forms.CharField(
|
||||||
max_length=200, label=_('Facebook author URL'), required=False
|
max_length=200, label=_('Facebook author URL'), required=False,
|
||||||
|
initial=get_setting('FB_AUTHOR_URL')
|
||||||
|
)
|
||||||
|
og_author = forms.CharField(
|
||||||
|
max_length=200, label=_('Facebook author'), required=False,
|
||||||
|
initial=get_setting('FB_AUTHOR')
|
||||||
)
|
)
|
||||||
twitter_type = forms.ChoiceField(
|
twitter_type = forms.ChoiceField(
|
||||||
label=_('Twitter type'), required=False,
|
label=_('Twitter type'), required=False,
|
||||||
choices=get_setting('TWITTER_TYPES'), initial=get_setting('TWITTER_TYPES')[0][0]
|
choices=get_setting('TWITTER_TYPES'), initial=get_setting('TWITTER_TYPE')
|
||||||
)
|
)
|
||||||
twitter_site = forms.CharField(
|
twitter_site = forms.CharField(
|
||||||
max_length=200, label=_('Twitter site handle'), required=False
|
max_length=200, label=_('Twitter site handle'), required=False,
|
||||||
|
initial=get_setting('TWITTER_SITE')
|
||||||
)
|
)
|
||||||
twitter_author = forms.CharField(
|
twitter_author = forms.CharField(
|
||||||
max_length=200, label=_('Twitter author handle'), required=False
|
max_length=200, label=_('Twitter author handle'), required=False,
|
||||||
|
initial=get_setting('TWITTER_AUTHOR')
|
||||||
)
|
)
|
||||||
gplus_type = forms.ChoiceField(
|
gplus_type = forms.ChoiceField(
|
||||||
label=_('Google+ type'), required=False,
|
label=_('Google+ type'), required=False,
|
||||||
choices=get_setting('GPLUS_TYPES'), initial=get_setting('GPLUS_TYPES')[0][0]
|
choices=get_setting('GPLUS_TYPES'), initial=get_setting('GPLUS_TYPE')
|
||||||
)
|
)
|
||||||
gplus_author = forms.CharField(
|
gplus_author = forms.CharField(
|
||||||
max_length=200, label=_('Google+ author name'), required=False
|
max_length=200, label=_('Google+ author name'), required=False,
|
||||||
|
initial=get_setting('GPLUS_AUTHOR')
|
||||||
)
|
)
|
||||||
setup_config(BlogConfigForm, BlogConfig)
|
setup_config(BlogConfigForm, BlogConfig)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ from django.utils.translation import get_language_from_request, ugettext_lazy as
|
||||||
from menus.base import NavigationNode
|
from menus.base import NavigationNode
|
||||||
from menus.menu_pool import menu_pool
|
from menus.menu_pool import menu_pool
|
||||||
|
|
||||||
|
from .cms_appconfig import BlogConfig
|
||||||
from .models import BlogCategory, Post
|
from .models import BlogCategory, Post
|
||||||
|
from .settings import MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_POSTS
|
||||||
|
|
||||||
|
|
||||||
class BlogCategoryMenu(CMSAttachMenu):
|
class BlogCategoryMenu(CMSAttachMenu):
|
||||||
|
|
@ -18,34 +20,52 @@ class BlogCategoryMenu(CMSAttachMenu):
|
||||||
|
|
||||||
language = get_language_from_request(request, check_path=True)
|
language = get_language_from_request(request, check_path=True)
|
||||||
|
|
||||||
categories = BlogCategory.objects
|
categories_menu = False
|
||||||
|
posts_menu = False
|
||||||
|
config = False
|
||||||
if hasattr(self, 'instance') and self.instance:
|
if hasattr(self, 'instance') and self.instance:
|
||||||
categories = categories.namespace(self.instance.application_namespace)
|
config = BlogConfig.objects.get(namespace=self.instance.application_namespace)
|
||||||
categories = categories.active_translations(language).distinct()
|
if config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_CATEGORIES):
|
||||||
categories = categories.order_by('parent__id', 'translations__name')
|
categories_menu = True
|
||||||
for category in categories:
|
if config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS):
|
||||||
node = NavigationNode(
|
posts_menu = True
|
||||||
category.name,
|
|
||||||
category.get_absolute_url(),
|
|
||||||
'%s-%s' % (category.__class__.__name__, category.pk),
|
|
||||||
('%s-%s' % (category.__class__.__name__, category.parent.id) if category.parent
|
|
||||||
else None)
|
|
||||||
)
|
|
||||||
nodes.append(node)
|
|
||||||
|
|
||||||
posts = Post.objects
|
if categories_menu:
|
||||||
if hasattr(self, 'instance') and self.instance:
|
categories = BlogCategory.objects
|
||||||
posts = posts.namespace(self.instance.application_namespace)
|
if config:
|
||||||
posts = posts.active_translations(language).distinct()
|
categories = categories.namespace(self.instance.application_namespace)
|
||||||
for post in posts:
|
categories = categories.active_translations(language).distinct()
|
||||||
category = post.categories.first()
|
categories = categories.order_by('parent__id', 'translations__name')
|
||||||
node = NavigationNode(
|
for category in categories:
|
||||||
post.get_title(),
|
node = NavigationNode(
|
||||||
post.get_absolute_url(language),
|
category.name,
|
||||||
'%s-%s' % (post.__class__.__name__, category.pk),
|
category.get_absolute_url(),
|
||||||
'%s-%s' % (category.__class__.__name__, category.pk)
|
'%s-%s' % (category.__class__.__name__, category.pk),
|
||||||
)
|
('%s-%s' % (category.__class__.__name__, category.parent.id) if category.parent
|
||||||
nodes.append(node)
|
else None)
|
||||||
|
)
|
||||||
|
nodes.append(node)
|
||||||
|
|
||||||
|
if posts_menu:
|
||||||
|
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:
|
||||||
|
if categories_menu:
|
||||||
|
category = post.categories.first()
|
||||||
|
parent = '%s-%s' % (category.__class__.__name__, category.pk)
|
||||||
|
post_id = '%s-%s' % (post.__class__.__name__, post.pk),
|
||||||
|
else:
|
||||||
|
parent = None
|
||||||
|
post_id = '%s-%s' % (post.__class__.__name__, post.pk),
|
||||||
|
node = NavigationNode(
|
||||||
|
post.get_title(),
|
||||||
|
post.get_absolute_url(language),
|
||||||
|
post_id,
|
||||||
|
parent
|
||||||
|
)
|
||||||
|
nodes.append(node)
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,15 @@
|
||||||
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 aldryn_apphooks_config.utils import get_app_instance
|
||||||
|
from django.core.cache import cache
|
||||||
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 smart_override, switch_language
|
from parler.utils.context import smart_override, switch_language
|
||||||
|
|
||||||
from djangocms_blog.views import CategoryEntriesView, PostDetailView
|
from djangocms_blog.views import CategoryEntriesView, PostDetailView
|
||||||
|
from djangocms_blog.settings import (
|
||||||
|
MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_NONE, MENU_TYPE_POSTS,
|
||||||
|
)
|
||||||
|
|
||||||
from . import BaseTest
|
from . import BaseTest
|
||||||
|
|
||||||
|
|
@ -44,6 +48,71 @@ class MenuTest(BaseTest):
|
||||||
cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)])
|
cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)])
|
||||||
self.assertTrue(cats_url.issubset(nodes_url))
|
self.assertTrue(cats_url.issubset(nodes_url))
|
||||||
|
|
||||||
|
def test_menu_options(self):
|
||||||
|
"""
|
||||||
|
Tests menu structure based on menu_structure configuration
|
||||||
|
"""
|
||||||
|
posts = self.get_posts()
|
||||||
|
self.get_pages()
|
||||||
|
|
||||||
|
cats_url = {}
|
||||||
|
posts_url = {}
|
||||||
|
|
||||||
|
languages = ('en', 'it')
|
||||||
|
|
||||||
|
for lang in languages:
|
||||||
|
with smart_override(lang):
|
||||||
|
cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)])
|
||||||
|
posts_url[lang] = set([post.get_absolute_url() for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1])
|
||||||
|
|
||||||
|
# No item in the menu
|
||||||
|
self.app_config_1.app_data.config.menu_structure = MENU_TYPE_NONE
|
||||||
|
self.app_config_1.save()
|
||||||
|
cache.clear()
|
||||||
|
for lang in languages:
|
||||||
|
request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang)
|
||||||
|
with smart_override(lang):
|
||||||
|
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
|
||||||
|
nodes_url = set([node.url for node in nodes])
|
||||||
|
self.assertFalse(cats_url[lang].issubset(nodes_url))
|
||||||
|
self.assertFalse(posts_url[lang].issubset(nodes_url))
|
||||||
|
|
||||||
|
# Only posts in the menu
|
||||||
|
self.app_config_1.app_data.config.menu_structure = MENU_TYPE_POSTS
|
||||||
|
self.app_config_1.save()
|
||||||
|
cache.clear()
|
||||||
|
for lang in languages:
|
||||||
|
request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang)
|
||||||
|
with smart_override(lang):
|
||||||
|
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
|
||||||
|
nodes_url = set([node.url for node in nodes])
|
||||||
|
self.assertFalse(cats_url[lang].issubset(nodes_url))
|
||||||
|
self.assertTrue(posts_url[lang].issubset(nodes_url))
|
||||||
|
|
||||||
|
# Only categories in the menu
|
||||||
|
self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES
|
||||||
|
self.app_config_1.save()
|
||||||
|
cache.clear()
|
||||||
|
for lang in languages:
|
||||||
|
request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang)
|
||||||
|
with smart_override(lang):
|
||||||
|
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
|
||||||
|
nodes_url = set([node.url for node in nodes])
|
||||||
|
self.assertTrue(cats_url[lang].issubset(nodes_url))
|
||||||
|
self.assertFalse(posts_url[lang].issubset(nodes_url))
|
||||||
|
|
||||||
|
# Both types in the menu
|
||||||
|
self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE
|
||||||
|
self.app_config_1.save()
|
||||||
|
cache.clear()
|
||||||
|
for lang in languages:
|
||||||
|
request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang)
|
||||||
|
with smart_override(lang):
|
||||||
|
nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu')
|
||||||
|
nodes_url = set([node.url for node in nodes])
|
||||||
|
self.assertTrue(cats_url[lang].issubset(nodes_url))
|
||||||
|
self.assertTrue(posts_url[lang].issubset(nodes_url))
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue