英文:
Django CMS icon in menu
问题
这是我扩展的模型:
class IconExtension(PageExtension):
image = models.ImageField(upload_to='icons')
extension_pool.register(IconExtension)
这是我的cms_toolbars.py文件:
@toolbar_pool.register
class IconExtensionToolbar(ExtensionToolbar):
model = IconExtension
def populate(self):
current_page_menu = self._setup_extension_toolbar()
if current_page_menu:
page_extension, url = self.get_page_extension_admin()
if url:
current_page_menu.add_modal_item(_('Page Icon'), url=url,
disabled=not self.toolbar.edit_mode_active, position=0)
这是我的menu.html文件的部分代码:
{% load menu_tags %}
{% for child in children %}
<li class="child{% if child.selected %} selected{% endif %}{% if child.ancestor %} ancestor{% endif %}{% if child.sibling %} sibling{% endif %}{% if child.descendant %} descendant{% endif %}">
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}
<img src="{{ child.image.url }}">
</a>
{% if child.children %}
<ul>
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% endif %}
</li>
{% endfor %}
请注意,这是您提供的代码的翻译版本,不包括额外的解释或评论。
英文:
I am trying to show my uploaded icon on navigation but i guess, i am going through a wrong way.
this is my model that extended
class IconExtension(PageExtension):
image = models.ImageField(upload_to='icons')
extension_pool.register(IconExtension)
and this is my cms_toolbars.py file
@toolbar_pool.register
class IconExtensionToolbar(ExtensionToolbar):
# defines the model for the current toolbar
model = IconExtension
def populate(self):
# setup the extension toolbar with permissions and sanity checks
current_page_menu = self._setup_extension_toolbar()
# if it's all ok
if current_page_menu:
# retrieves the instance of the current extension (if any) and the toolbar item URL
page_extension, url = self.get_page_extension_admin()
if url:
# adds a toolbar item in position 0 (at the top of the menu)
current_page_menu.add_modal_item(_('Page Icon'), url=url,
disabled=not self.toolbar.edit_mode_active, position=0)
and this is my menu.html file
{% load menu_tags %}
{% for child in children %}
<li class="child{% if child.selected %} selected{% endif %}{% if child.ancestor %} ancestor{% endif %}{% if child.sibling %} sibling{% endif %}{% if child.descendant %} descendant{% endif %}">
<a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}
<img src="{{ child.image.url }}">
</a>
{% if child.children %}
<ul>
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% endif %}
</li>
{% endfor %}
I am not getting why it is not working, I don't see any error even I don't see any image url here, my everything is working fine, only going through problem showing menu icon, can anyone help me in this case?
答案1
得分: 1
It looks like you're just missing the reference to the object from the page, you're going straight to its attribute.
I've got a very similar setup with images associated with pages;
class PageImage(PageExtension):
""" Add images to pages """
image = models.FileField(
verbose_name=_("Image"),
upload_to=upload_to('page_images')
)
Which in my templates becomes;
{% if request.current_page.pageimage.image %}
{{ request.current_page.pageimage.image.url }}
{% endif %}
So in your example, if you did this in a template you'd do;
{% if request.current_page.iconextension %}
<img src="{{ request.current_page.iconextension.image.url }}">
{% endif %}
Checking if the extension exists is important to avoid attribute errors etc.
In a menu, the child
isn't a Page
object though, it's a NavigationNode
from the menu system. So it doesn't have your extension.
I think the proper solution to this is to set up a navigation Modifier
. The docs for this are here; http://docs.django-cms.org/en/latest/how_to/menus.html#navigation-modifiers
Alternatively, you could set up a template tag which you pass your child
, which could then use the reverse_id
attribute to query the database for the Page
that corresponds to, and return the iconextension
of that page. I've used this method before.
英文:
It looks like you're just missing the reference to the object from the page, you're going straight to it's attribute.
I've got a very similar setup with images associated with pages;
class PageImage(PageExtension):
""" Add images to pages """
image = models.FileField(
verbose_name=_("Image"),
upload_to=upload_to('page_images')
)
Which in my templates becomes;
{% if request.current_page.pageimage.image %}
{{ request.current_page.pageimage.image.url }}
{% endif %}
So in your example, if you did this in a template you'd do;
{% if request.current_page.iconextension %}
<img src="{{ request.current_page.iconextension.image.url }}">
{% endif %}
Checking if the extension exists is important to avoid attribute errors etc.
In a menu, the child
isn't a Page
object though, it's a NavigationNode
from the menu system. So it doesn't have your extension.
I think the proper solution to this is to setup a navigation Modifier
. The docs for this are here; http://docs.django-cms.org/en/latest/how_to/menus.html#navigation-modifiers
Alternatively you could setup a template tag which you pass your child
which could then use the reverse_id
attribute to query the database for the Page
that corresponds to, and return the iconextension
of that page. I've used this method before.
答案2
得分: 0
根据@markwalker_的回答,我成功地完成了3个步骤:
步骤1 - 在页面扩展中添加一个FontAwesomeField:
https://docs.django-cms.org/en/latest/how_to/extending_page_title.html
记录一下我的代码:
在 models.py 中:
from django.db import models
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool
class IconExtension(PageExtension):
image = models.ImageField(upload_to='icons', null=True, blank=True)
fontawesomeicon = models.CharField(max_length=100, null=True, blank=True)
extension_pool.register(IconExtension)
在 admin.py 中:
from django.contrib import admin
from cms.extensions import PageExtensionAdmin
from .models import IconExtension
class IconExtensionAdmin(PageExtensionAdmin):
pass
admin.site.register(IconExtension, IconExtensionAdmin)
在 cms_toolbars.py 中:
from cms.toolbar_pool import toolbar_pool
from cms.extensions.toolbar import ExtensionToolbar
from django.utils.translation import gettext_lazy as _
from .models import IconExtension
@toolbar_pool.register
class IconExtensionToolbar(ExtensionToolbar):
model = IconExtension
def populate(self):
current_page_menu = self._setup_extension_toolbar()
if current_page_menu:
page_extension, url = self.get_page_extension_admin()
if url:
current_page_menu.add_modal_item(_('Page Icon'), url=url,
disabled=not self.toolbar.edit_mode_active, position=0)
步骤2 - 实现导航修饰器:
https://docs.django-cms.org/en/latest/how_to/menus.html#navigation-modifiers
在 cms_menu.py 中:
from menus.base import Modifier
from menus.menu_pool import menu_pool
from cms.models import Page
class AddIconModifier(Modifier):
"""
This modifier makes the changed_by attribute of a page
accessible for the menu system.
"""
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
if breadcrumb:
return nodes
if not post_cut:
return nodes
page_nodes = {n.id: n for n in nodes if n.attr["is_page"]}
pages = Page.objects.filter(id__in=page_nodes.keys())
for page in pages:
node = page_nodes[page.id]
if hasattr(page, 'iconextension') and hasattr(page.iconextension, 'fontawesomeicon'):
node.attr["faicon"] = page.iconextension.fontawesomeicon
else:
node.attr["faicon"] = 'fa-arrow-circle-right'
return nodes
menu_pool.register_modifier(AddIconModifier)
步骤3 - 特定导航模板:
在我的主模板中:
{% show_menu 0 100 100 100 "partials/navigation.html" %}
在我的导航模板(navigation.html)中:
{% load cms_tags menu_tags cache %}
{% for child in children %}
<li class="nav-item">
<a class="nav-link" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}"><i class="fas fa-fw {{ child.attr.faicon }}"></i>{{ child.get_menu_title }}</a>
{% if child.children %}
<ul class="sub_menu">
{% show_menu from_level to_level extra_inactive extra_active template '' '' child %}
</ul>
{% endif %}
</li>
{% endfor %}
英文:
Based on @markwalker_ answer. I did the job successfully in 3 Steps
Step 1 - Add an FontAwesomeField in a page Extension :
https://docs.django-cms.org/en/latest/how_to/extending_page_title.html
For the record here is my code :
In models.py
from django.db import models
# Create your models here.
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool
class IconExtension(PageExtension):
image = models.ImageField(upload_to='icons', null=True, blank=True)
fontawesomeicon = models.CharField(max_length=100, null=True, blank=True)
extension_pool.register(IconExtension)
In admin.py
from django.contrib import admin
from cms.extensions import PageExtensionAdmin
from .models import IconExtension
class IconExtensionAdmin(PageExtensionAdmin):
pass
admin.site.register(IconExtension, IconExtensionAdmin)
In cms_toolbars.py
from cms.toolbar_pool import toolbar_pool
from cms.extensions.toolbar import ExtensionToolbar
from django.utils.translation import gettext_lazy as _
from .models import IconExtension
@toolbar_pool.register
class IconExtensionToolbar(ExtensionToolbar):
# defines the model for the current toolbar
model = IconExtension
def populate(self):
# setup the extension toolbar with permissions and sanity checks
current_page_menu = self._setup_extension_toolbar()
# if it's all ok
if current_page_menu:
# retrieves the instance of the current extension (if any) and the toolbar item URL
page_extension, url = self.get_page_extension_admin()
if url:
# adds a toolbar item in position 0 (at the top of the menu)
current_page_menu.add_modal_item(_('Page Icon'), url=url,
disabled=not self.toolbar.edit_mode_active, position=0)
Step 2 - Implementing Navigation Modifier
https://docs.django-cms.org/en/latest/how_to/menus.html#navigation-modifiers
In cms_menu.py
from menus.base import Modifier
from menus.menu_pool import menu_pool
from cms.models import Page
class AddIconModifier(Modifier):
"""
This modifier makes the changed_by attribute of a page
accessible for the menu system.
"""
def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
if breadcrumb:
return nodes
# Only on last iteration (Voir : https://docs.django-cms.org/en/latest/how_to/menus.html#navigation-modifiers)
if not post_cut:
return nodes
# only consider nodes that refer to cms pages
# and put them in a dict for efficient access
page_nodes = {n.id: n for n in nodes if n.attr["is_page"]}
# retrieve the relevent pages
pages = Page.objects.filter(id__in=page_nodes.keys())
# loop over all relevant pages
for page in pages:
# take the node referring to the page
node = page_nodes[page.id]
if hasattr(page, 'iconextension') and hasattr(page.iconextension ,'fontawesomeicon'):
node.attr["faicon"] = page.iconextension.fontawesomeicon
else:
node.attr["faicon"] = 'fa-arrow-circle-right'
return nodes
menu_pool.register_modifier(AddIconModifier)
Step 3 - Specific navigation template
In my main template :
{% show_menu 0 100 100 100 "partials/navigation.html" %}
In my navigation template (navigation.html)
{% load cms_tags menu_tags cache %}
{% for child in children %}
<li class="nav-item">
<a class="nav-link" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}"><i class="fas fa-fw {{ child.attr.faicon }}"></i>{{ child.get_menu_title }}</a>
{% if child.children %}
<ul class="sub_menu">
{% show_menu from_level to_level extra_inactive extra_active template '' '' child %}
</ul>
{% endif %}
</li>
{% endfor %}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论