Reputation: 18442
I want to integrate an app to Django CMS. Therefor I followed the documentation of Django CMS.
For example: I use the following code (from doc) in menu.py of my app.
from menus.base import Menu, NavigationNode
from menus.menu_pool import menu_pool
from django.utils.translation import ugettext_lazy as _
class TestMenu(Menu):
def get_nodes(self, request):
nodes = []
n = NavigationNode(_('sample root page'), "/", 1)
n2 = NavigationNode(_('sample settings page'), "/bye/", 2)
n3 = NavigationNode(_('sample account page'), "/hello/", 3)
n4 = NavigationNode(_('sample my profile page'), "/hello/world/", 4, 3)
nodes.append(n)
nodes.append(n2)
nodes.append(n3)
nodes.append(n4)
return nodes
menu_pool.register_menu(TestMenu)
My problem is the order of the nodes. With this code my menu will be appended on the menu of my cms pages, but I need a different order.
Is there some way to define on which position my app menu appears?
Upvotes: 4
Views: 1588
Reputation: 6990
Thanks for helping me out, Sven!! I wasn't aware of the existence of modifiers...
Below is a refinement of your code. It will insert app nodes at arbitrary locations. Each app node has a targetIndex attribute, giving it's zero-based place number on the menu. Sorry for the camel-case, but I use a mix of programming languages and one style to fit them all. In the example, app nodes are inserted at even place numbers, 'follow' is the name of my app.
from menus.base import Menu, NavigationNode, Modifier
from menus.menu_pool import menu_pool
class FollowMenu (Menu):
def get_nodes (self, request):
nodes = []
for i in range (5):
nodes.append (NavigationNode (('Test' + str (i)), '/', i, attr={'targetIndex': 2 * i}))
return nodes
menu_pool.register_menu (FollowMenu)
class FollowModifier (Modifier):
def modify (self, request, nodes, namespace, root_id, post_cut, breadcrumb):
if not post_cut:
return nodes
appNodes = [node for node in nodes if 'targetIndex' in node.attr]
cmsNodes = [node for node in nodes if not 'targetIndex' in node.attr]
resultNodes = []
appNodeIndex = 0
cmsNodeIndex = 0
for resultNodeIndex in range (len (nodes)):
if appNodeIndex < len (appNodes) and appNodes [appNodeIndex] .attr ['targetIndex'] == resultNodeIndex:
resultNodes.append (appNodes [appNodeIndex])
appNodeIndex += 1
elif cmsNodeIndex < len (cmsNodes):
resultNodes.append (cmsNodes [cmsNodeIndex])
cmsNodeIndex += 1
else:
raise Exception ('Error merging app menu and cms menu items')
return resultNodes
menu_pool.register_modifier (FollowModifier)
Upvotes: 0
Reputation: 18442
Here is my workaround, so far. (I still would prefer a more clean way.)
I added a CMS page named --appname--
and this is my menu.py
:
from menus.base import Menu, NavigationNode
from menus.base import Modifier
from menus.menu_pool import menu_pool
my_items = ["a", "b", "c"]
class ImmoMenu(Menu):
def get_nodes(self, request):
nodes = []
i = 0
for name in my_items:
i += 1
n = NavigationNode(name, "/", i, attr={'appname': True})
nodes.append(n)
return nodes
menu_pool.register_menu(ImmoMenu)
class ImmoModifier(Modifier):
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
if post_cut is not True:
return nodes
split_passed = False
nodes_before = []
nodes_after = []
nodes_immo = []
for node in nodes:
if node.title == "--appname--":
split_passed = True
continue
if 'appname' in node.attr:
nodes_immo.append(node)
elif split_passed:
nodes_after.append(node)
else:
nodes_before.append(node)
return nodes_before + nodes_immo + nodes_after
menu_pool.register_modifier(ImmoModifier)
Upvotes: 3