Merge pull request #237 from nephila/feature/move_menus

Add some compatibility for cms menu and filer
This commit is contained in:
Iacopo Spalletti 2016-04-29 12:12:19 +02:00
commit 88b8e0c738
4 changed files with 163 additions and 147 deletions

145
djangocms_blog/cms_menus.py Normal file
View file

@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
from cms.apphook_pool import apphook_pool
from cms.menu_bases import CMSAttachMenu
from django.core.urlresolvers import resolve
from django.db.models.signals import post_delete, post_save
from django.utils.translation import get_language_from_request, ugettext_lazy as _
from menus.base import Modifier, NavigationNode
from menus.menu_pool import menu_pool
from .cms_appconfig import BlogConfig
from .models import BlogCategory, Post
from .settings import MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_POSTS, get_setting
class BlogCategoryMenu(CMSAttachMenu):
"""
Main menu class
Handles all types of blog menu
"""
name = _('Blog menu')
def get_nodes(self, request):
"""
Generates the nodelist
:param request:
:return: list of nodes
"""
nodes = []
language = get_language_from_request(request, check_path=True)
categories_menu = False
posts_menu = False
config = False
if hasattr(self, 'instance') and self.instance:
config = BlogConfig.objects.get(namespace=self.instance.application_namespace)
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_CATEGORIES):
categories_menu = True
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS):
posts_menu = True
if categories_menu:
categories = BlogCategory.objects
if config:
categories = categories.namespace(self.instance.application_namespace)
categories = categories.active_translations(language).distinct()
categories = categories.order_by('parent__id', 'translations__name')
for category in categories:
node = NavigationNode(
category.name,
category.get_absolute_url(),
'{0}-{1}'.format(category.__class__.__name__, category.pk),
(
'{0}-{1}'.format(
category.__class__.__name__, category.parent.id
) if category.parent else None
)
)
nodes.append(node)
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:
post_id = None
parent = None
if categories_menu:
category = post.categories.first()
if category:
parent = '{0}-{1}'.format(category.__class__.__name__, category.pk)
post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk),
else:
post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk),
if post_id:
node = NavigationNode(
post.get_title(),
post.get_absolute_url(language),
post_id,
parent
)
nodes.append(node)
return nodes
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):
"""
Actual modifier function
:param request: request
:param nodes: complete list of nodes
:param namespace: Menu namespace
:param root_id: eventual root_id
:param post_cut: flag for modifier stage
:param breadcrumb: flag for modifier stage
:return: nodeslist
"""
app = None
config = None
if getattr(request, 'current_page', None) and request.current_page.application_urls:
app = apphook_pool.get_apphook(request.current_page.application_urls)
if app and app.app_config:
namespace = resolve(request.path).namespace
config = app.get_config(namespace)
if config and config.menu_structure != MENU_TYPE_CATEGORIES:
return nodes
if post_cut:
return nodes
current_post = getattr(request, get_setting('CURRENT_POST_IDENTIFIER'), None)
category = None
if current_post and current_post.__class__ == Post:
category = current_post.categories.first()
if not category:
return nodes
for node in nodes:
if '{0}-{1}'.format(category.__class__.__name__, category.pk) == node.id:
node.selected = True
return nodes
menu_pool.register_modifier(BlogNavModifier)
def clear_menu_cache(**kwargs):
"""
Empty menu cache when saving categories
"""
menu_pool.clear(all=True)
post_save.connect(clear_menu_cache, sender=BlogCategory)
post_delete.connect(clear_menu_cache, sender=BlogCategory)

View file

@ -1,145 +1,2 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals from djangocms_blog.cms_menus import * # NOQA
from cms.apphook_pool import apphook_pool
from cms.menu_bases import CMSAttachMenu
from django.core.urlresolvers import resolve
from django.db.models.signals import post_delete, post_save
from django.utils.translation import get_language_from_request, ugettext_lazy as _
from menus.base import Modifier, NavigationNode
from menus.menu_pool import menu_pool
from .cms_appconfig import BlogConfig
from .models import BlogCategory, Post
from .settings import MENU_TYPE_CATEGORIES, MENU_TYPE_COMPLETE, MENU_TYPE_POSTS, get_setting
class BlogCategoryMenu(CMSAttachMenu):
"""
Main menu class
Handles all types of blog menu
"""
name = _('Blog menu')
def get_nodes(self, request):
"""
Generates the nodelist
:param request:
:return: list of nodes
"""
nodes = []
language = get_language_from_request(request, check_path=True)
categories_menu = False
posts_menu = False
config = False
if hasattr(self, 'instance') and self.instance:
config = BlogConfig.objects.get(namespace=self.instance.application_namespace)
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_CATEGORIES):
categories_menu = True
if config and config.menu_structure in (MENU_TYPE_COMPLETE, MENU_TYPE_POSTS):
posts_menu = True
if categories_menu:
categories = BlogCategory.objects
if config:
categories = categories.namespace(self.instance.application_namespace)
categories = categories.active_translations(language).distinct()
categories = categories.order_by('parent__id', 'translations__name')
for category in categories:
node = NavigationNode(
category.name,
category.get_absolute_url(),
'{0}-{1}'.format(category.__class__.__name__, category.pk),
(
'{0}-{1}'.format(
category.__class__.__name__, category.parent.id
) if category.parent else None
)
)
nodes.append(node)
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:
post_id = None
parent = None
if categories_menu:
category = post.categories.first()
if category:
parent = '{0}-{1}'.format(category.__class__.__name__, category.pk)
post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk),
else:
post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk),
if post_id:
node = NavigationNode(
post.get_title(),
post.get_absolute_url(language),
post_id,
parent
)
nodes.append(node)
return nodes
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):
"""
Actual modifier function
:param request: request
:param nodes: complete list of nodes
:param namespace: Menu namespace
:param root_id: eventual root_id
:param post_cut: flag for modifier stage
:param breadcrumb: flag for modifier stage
:return: nodeslist
"""
app = None
config = None
if getattr(request, 'current_page', None) and request.current_page.application_urls:
app = apphook_pool.get_apphook(request.current_page.application_urls)
if app and app.app_config:
namespace = resolve(request.path).namespace
config = app.get_config(namespace)
if config and config.menu_structure != MENU_TYPE_CATEGORIES:
return nodes
if post_cut:
return nodes
current_post = getattr(request, get_setting('CURRENT_POST_IDENTIFIER'), None)
category = None
if current_post and current_post.__class__ == Post:
category = current_post.categories.first()
if not category:
return nodes
for node in nodes:
if '{0}-{1}'.format(category.__class__.__name__, category.pk) == node.id:
node.selected = True
return nodes
menu_pool.register_modifier(BlogNavModifier)
def clear_menu_cache(**kwargs):
"""
Empty menu cache when saving categories
"""
menu_pool.clear(all=True)
post_save.connect(clear_menu_cache, sender=BlogCategory)
post_delete.connect(clear_menu_cache, sender=BlogCategory)

View file

@ -3,7 +3,6 @@ from __future__ import absolute_import, print_function, unicode_literals
from copy import deepcopy from copy import deepcopy
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.core.cache import cache from django.core.cache import cache
@ -15,6 +14,13 @@ from parler.utils.context import smart_override
from djangocms_blog.cms_appconfig import BlogConfig from djangocms_blog.cms_appconfig import BlogConfig
from djangocms_blog.models import BlogCategory, Post from djangocms_blog.models import BlogCategory, Post
try:
from filer.models import ThumbnailOption # NOQA
except ImportError:
from cmsplugin_filer_image.models import ThumbnailOption # NOQA
User = get_user_model() User = get_user_model()

12
tox.ini
View file

@ -13,8 +13,6 @@ deps =
django18: django-mptt>=0.8 django18: django-mptt>=0.8
django19: Django>=1.9,<1.10 django19: Django>=1.9,<1.10
django19: django-mptt>=0.8 django19: django-mptt>=0.8
django19: https://github.com/divio/django-filer/archive/develop.zip
django19: https://github.com/divio/cmsplugin-filer/archive/develop.zip
cms30: https://github.com/divio/django-cms/archive/support/3.0.x.zip cms30: https://github.com/divio/django-cms/archive/support/3.0.x.zip
cms31: https://github.com/divio/django-cms/archive/support/3.1.x.zip cms31: https://github.com/divio/django-cms/archive/support/3.1.x.zip
cms32: https://github.com/divio/django-cms/archive/release/3.2.x.zip cms32: https://github.com/divio/django-cms/archive/release/3.2.x.zip
@ -23,6 +21,16 @@ deps =
django-meta>=1.2 django-meta>=1.2
https://github.com/nephila/djangocms-helper/archive/develop.zip https://github.com/nephila/djangocms-helper/archive/develop.zip
py26: unittest2 py26: unittest2
py26: django-filer<1.2
py26: cmsplugin-filer<1.1
py27: django-filer<1.3
py27: cmsplugin-filer<1.2
py33: django-filer<1.3
py33: cmsplugin-filer<1.2
py34: django-filer<1.3
py34: cmsplugin-filer<1.2
py35: django-filer<1.3
py35: cmsplugin-filer<1.2
https://github.com/aldryn/aldryn-apphooks-config/archive/master.zip https://github.com/aldryn/aldryn-apphooks-config/archive/master.zip
https://github.com/nephila/djangocms-apphook-setup/archive/master.zip https://github.com/nephila/djangocms-apphook-setup/archive/master.zip
-r{toxinidir}/requirements-test.txt -r{toxinidir}/requirements-test.txt