DjangoCMS NavigationNode - 自定义节点
DjangoCMS NavigationNode - custom node
DjangoCMS 中的默认 NavigationNode 具有以下节点:
- children
- 标题
- get_menu_title
- get_attribute
- 等等
在相同的上下文中,我想添加我的自定义节点,名为:category_name 它将 return一个字符串 'something' (仅用于测试目的)。
在 official documentation 之后,没有找到任何可以帮助我解决问题的方法。在查找default NavigationNode的声明时,出现如下代码:
from menus.base import NavigationNode
base.py 文件:
class NavigationNode(object):
def __init__(self, title, url, id, parent_id=None, parent_namespace=None,
attr=None, visible=True):
self.children = [] # do not touch
self.parent = None # do not touch, code depends on this
self.namespace = None # TODO: Assert why we need this and above
self.title = title
self.url = url
self.id = id
self.parent_id = parent_id
self.parent_namespace = parent_namespace
self.visible = visible
self.attr = attr or {} # To avoid declaring a dict in defaults...
def __repr__(self):
return "<Navigation Node: %s>" % smart_str(self.title)
def get_menu_title(self):
return self.title
def get_absolute_url(self):
return self.url
def get_attribute(self, name):
return self.attr.get(name, None)
def get_descendants(self):
return sum(([node] + node.get_descendants() for node in self.children), [])
def get_ancestors(self):
if getattr(self, 'parent', None):
return [self.parent] + self.parent.get_ancestors()
else:
return []
如果我在此处添加名为 category_name 的自定义节点,它将起作用。但是修改基础文件并不是一个明智的解决方案。
所以我的问题是:
How to add my custom node outside the base.py ? i.E. if I want to add
it in my apps models.py file. Is this even possible?
我终于找到了解决办法。答案是:是的!有可能的。
如文档中所述,您可以使用 modify() 方法。
但这对我不起作用,因为我对 node.attr["changed_by"]
感到困惑。在模板中,我想使用这样的东西:{{ child.category_name }}
但很明显,我修改错了。
正确的方法是这样的:
from menus.base import Modifier
from menus.menu_pool import menu_pool
from cms.models import Page
class MyMode(Modifier):
"""
"""
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
# if the menu is not yet cut, don't do anything
if post_cut:
return nodes
# otherwise loop over the nodes
for node in nodes:
# does this node represent a Page?
if node.attr["is_page"]:
# if so, put its changed_by attribute on the node
node.category_name = "Some category name here"
return nodes
menu_pool.register_modifier(MyMode)
现在,在menu.html中,你可以使用child.category_name,它会输出字符串"Some category name here"
{% load i18n menu_tags cache %}
{% for child in children %}
<li>
{% if child.children %}
<a href="{{ child.get_absolute_url }}">
{{ child.get_menu_title }} <span class="caret"></span>
</a>
<ul class="menu-vertical">
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% else %}
<a class1="{{ child.get_absolute_url }}" href="{{ child.get_absolute_url }}">
{% if child.category_name %}
<b>{{ child.category }}</b>
{% endif %}
{{ child.get_menu_title }}
</a>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}
最后,经过数小时的尝试,我解决了这个问题。
DjangoCMS 中的默认 NavigationNode 具有以下节点:
- children
- 标题
- get_menu_title
- get_attribute
- 等等
在相同的上下文中,我想添加我的自定义节点,名为:category_name 它将 return一个字符串 'something' (仅用于测试目的)。
在 official documentation 之后,没有找到任何可以帮助我解决问题的方法。在查找default NavigationNode的声明时,出现如下代码:
from menus.base import NavigationNode
base.py 文件:
class NavigationNode(object):
def __init__(self, title, url, id, parent_id=None, parent_namespace=None,
attr=None, visible=True):
self.children = [] # do not touch
self.parent = None # do not touch, code depends on this
self.namespace = None # TODO: Assert why we need this and above
self.title = title
self.url = url
self.id = id
self.parent_id = parent_id
self.parent_namespace = parent_namespace
self.visible = visible
self.attr = attr or {} # To avoid declaring a dict in defaults...
def __repr__(self):
return "<Navigation Node: %s>" % smart_str(self.title)
def get_menu_title(self):
return self.title
def get_absolute_url(self):
return self.url
def get_attribute(self, name):
return self.attr.get(name, None)
def get_descendants(self):
return sum(([node] + node.get_descendants() for node in self.children), [])
def get_ancestors(self):
if getattr(self, 'parent', None):
return [self.parent] + self.parent.get_ancestors()
else:
return []
如果我在此处添加名为 category_name 的自定义节点,它将起作用。但是修改基础文件并不是一个明智的解决方案。
所以我的问题是:
How to add my custom node outside the base.py ? i.E. if I want to add it in my apps models.py file. Is this even possible?
我终于找到了解决办法。答案是:是的!有可能的。
如文档中所述,您可以使用 modify() 方法。
但这对我不起作用,因为我对 node.attr["changed_by"]
感到困惑。在模板中,我想使用这样的东西:{{ child.category_name }}
但很明显,我修改错了。
正确的方法是这样的:
from menus.base import Modifier
from menus.menu_pool import menu_pool
from cms.models import Page
class MyMode(Modifier):
"""
"""
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
# if the menu is not yet cut, don't do anything
if post_cut:
return nodes
# otherwise loop over the nodes
for node in nodes:
# does this node represent a Page?
if node.attr["is_page"]:
# if so, put its changed_by attribute on the node
node.category_name = "Some category name here"
return nodes
menu_pool.register_modifier(MyMode)
现在,在menu.html中,你可以使用child.category_name,它会输出字符串"Some category name here"
{% load i18n menu_tags cache %}
{% for child in children %}
<li>
{% if child.children %}
<a href="{{ child.get_absolute_url }}">
{{ child.get_menu_title }} <span class="caret"></span>
</a>
<ul class="menu-vertical">
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% else %}
<a class1="{{ child.get_absolute_url }}" href="{{ child.get_absolute_url }}">
{% if child.category_name %}
<b>{{ child.category }}</b>
{% endif %}
{{ child.get_menu_title }}
</a>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}
最后,经过数小时的尝试,我解决了这个问题。