From 2588f6c020210a5cd1620e558c0c3129372f0d01 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Mon, 15 Feb 2016 20:33:17 +0100 Subject: [PATCH 1/3] 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) From e5a070bc94c45e35c56f507cc3ba6997049591d0 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Mon, 15 Feb 2016 20:37:07 +0100 Subject: [PATCH 2/3] Fix string formatting --- djangocms_blog/menu.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/djangocms_blog/menu.py b/djangocms_blog/menu.py index 22660a8..6be7aad 100644 --- a/djangocms_blog/menu.py +++ b/djangocms_blog/menu.py @@ -53,9 +53,12 @@ class BlogCategoryMenu(CMSAttachMenu): node = NavigationNode( 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) + '{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) @@ -70,10 +73,10 @@ class BlogCategoryMenu(CMSAttachMenu): if categories_menu: category = post.categories.first() if category: - parent = '%s-%s' % (category.__class__.__name__, category.pk) - post_id = '%s-%s' % (post.__class__.__name__, post.pk), + parent = '{0}-{1}'.format(category.__class__.__name__, category.pk) + post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk), else: - post_id = '%s-%s' % (post.__class__.__name__, post.pk), + post_id = '{0}-{1}'.format(post.__class__.__name__, post.pk), if post_id: node = NavigationNode( post.get_title(), @@ -95,6 +98,16 @@ class BlogNavModifier(Modifier): 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: @@ -115,7 +128,7 @@ class BlogNavModifier(Modifier): return nodes for node in nodes: - if '%s-%s' % (category.__class__.__name__, category.pk) == node.id: + if '{0}-{1}'.format(category.__class__.__name__, category.pk) == node.id: node.selected = True return nodes From f79b6471c436132f6ac118257445f7c64128b824 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Mon, 15 Feb 2016 23:16:34 +0100 Subject: [PATCH 3/3] Fix test --- tests/test_menu.py | 35 +++++++++++++++++++---------------- tests/test_models.py | 2 +- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/test_menu.py b/tests/test_menu.py index 83980d2..8247368 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -140,14 +140,16 @@ 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'): with switch_language(obj, 'en'): + request = self.get_page_request( + pages[1], self.user, path=obj.get_absolute_url() + ) + cache.clear() + menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) @@ -157,22 +159,22 @@ class MenuTest(BaseTest): view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) - found = False + found = [] for node in nodes: if node.selected: - self.assertEqual(node.url, obj.get_absolute_url()) - found = True - break - self.assertTrue(found) + found.append(node.get_absolute_url()) + self.assertTrue(obj.get_absolute_url() in 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'): + request = self.get_page_request( + pages[1], self.user, path=obj.get_absolute_url() + ) + cache.clear() + menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) @@ -182,10 +184,11 @@ class MenuTest(BaseTest): view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) - found = False + found = [] for node in nodes: if node.selected: - self.assertEqual(node.url, cat.get_absolute_url()) - found = True - break - self.assertTrue(found) + found.append(node.get_absolute_url()) + self.assertTrue(cat.get_absolute_url() in found) + + self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE + self.app_config_1.save() diff --git a/tests/test_models.py b/tests/test_models.py index ab8977d..689e2ae 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -91,7 +91,7 @@ class AdminTest(BaseTest): for fieldname in BlogConfigForm.base_fields: self.assertContains(response, 'id="id_config-%s"' % fieldname) self.assertContains(response, '') - self.assertContains(response, '') + self.assertContains(response, 'sample_app') def test_admin_category_views(self): post_admin = admin.site._registry[BlogCategory]