From 2588f6c020210a5cd1620e558c0c3129372f0d01 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Mon, 15 Feb 2016 20:33:17 +0100 Subject: [PATCH] Fix selecting current menu item according to menu layout --- HISTORY.rst | 1 + djangocms_blog/menu.py | 54 ++++++++++++++++++++++++++++++++++++++++-- tests/test_menu.py | 31 ++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 76ae54f..6fda271 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,7 @@ History * Use all_languages_column to admin * Add publish button * Fix issues in migrations. Thanks @skirsdeda +* Fix selecting current menu item according to menu layout 0.6.3 (2015-12-22) ++++++++++++++++++ diff --git a/djangocms_blog/menu.py b/djangocms_blog/menu.py index 8d7920f..22660a8 100644 --- a/djangocms_blog/menu.py +++ b/djangocms_blog/menu.py @@ -1,21 +1,34 @@ # -*- 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 NavigationNode +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 +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) @@ -75,7 +88,44 @@ class BlogCategoryMenu(CMSAttachMenu): 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): + 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 '%s-%s' % (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) diff --git a/tests/test_menu.py b/tests/test_menu.py index 0f9f046..83980d2 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -29,6 +29,7 @@ class MenuTest(BaseTest): self.cats.append(cat) activate('en') + menu_pool.clear(all=True) menu_pool.discover_menus() # All cms menu modifiers should be removed from menu_pool.modifiers # so that they do not interfere with our menu nodes @@ -139,6 +140,10 @@ class MenuTest(BaseTest): (PostDetailView, 'slug', posts[0], posts[0].categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) + menu_pool.clear(all=True) + cache.clear() + self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE + self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) with smart_override('en'): @@ -149,6 +154,7 @@ class MenuTest(BaseTest): view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) + view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = False @@ -158,3 +164,28 @@ class MenuTest(BaseTest): found = True break self.assertTrue(found) + + menu_pool.clear(all=True) + cache.clear() + self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES + self.app_config_1.save() + for view_cls, kwarg, obj, cat in tests: + request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) + with smart_override('en'): + with switch_language(obj, 'en'): + view_obj = view_cls() + view_obj.request = request + view_obj.namespace, view_obj.config = get_app_instance(request) + view_obj.app_config = self.app_config_1 + view_obj.kwargs = {kwarg: obj.slug} + view_obj.get(request) + view_obj.get_context_data() + # check if selected menu node points to cat + nodes = menu_pool.get_nodes(request) + found = False + for node in nodes: + if node.selected: + self.assertEqual(node.url, cat.get_absolute_url()) + found = True + break + self.assertTrue(found)