Django CMS 菜单中的图标

huangapple go评论63阅读模式
英文:

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=&#39;icons&#39;)


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&#39;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(_(&#39;Page Icon&#39;), 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 %}
&lt;li class=&quot;child{% if child.selected %} selected{% endif %}{% if child.ancestor %} ancestor{% endif %}{% if child.sibling %} sibling{% endif %}{% if child.descendant %} descendant{% endif %}&quot;&gt;
	&lt;a href=&quot;{{ child.attr.redirect_url|default:child.get_absolute_url }}&quot;&gt;{{ child.get_menu_title }}
    &lt;img src=&quot;{{ child.image.url }}&quot;&gt;
  &lt;/a&gt;
	{% if child.children %}
	&lt;ul&gt;
		{% show_menu from_level to_level extra_inactive extra_active template &quot;&quot; &quot;&quot; child %}
	&lt;/ul&gt;
	{% endif %}
&lt;/li&gt;
{% 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):
    &quot;&quot;&quot; Add images to pages &quot;&quot;&quot;
    image = models.FileField(
        verbose_name=_(&quot;Image&quot;),
        upload_to=upload_to(&#39;page_images&#39;)
    )

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 %}
    &lt;img src=&quot;{{ request.current_page.iconextension.image.url }}&quot;&gt;
{% 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=&#39;icons&#39;, 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&#39;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(_(&#39;Page Icon&#39;), 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):
    &quot;&quot;&quot;
    This modifier makes the changed_by attribute of a page
    accessible for the menu system.
    &quot;&quot;&quot;

    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[&quot;is_page&quot;]}
        # 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, &#39;iconextension&#39;) and hasattr(page.iconextension ,&#39;fontawesomeicon&#39;):
                node.attr[&quot;faicon&quot;] = page.iconextension.fontawesomeicon
            else:
                node.attr[&quot;faicon&quot;] = &#39;fa-arrow-circle-right&#39;
        
        return nodes


menu_pool.register_modifier(AddIconModifier)

Step 3 - Specific navigation template
In my main template :

{% show_menu 0 100 100 100 &quot;partials/navigation.html&quot; %}

In my navigation template (navigation.html)

{% load cms_tags menu_tags cache %}

{% for child in children %}

    &lt;li class=&quot;nav-item&quot;&gt;
        &lt;a class=&quot;nav-link&quot; href=&quot;{{ child.attr.redirect_url|default:child.get_absolute_url }}&quot;&gt;&lt;i class=&quot;fas fa-fw {{ child.attr.faicon }}&quot;&gt;&lt;/i&gt;{{ child.get_menu_title }}&lt;/a&gt;
        {% if child.children %}
            &lt;ul class=&quot;sub_menu&quot;&gt;
                {% show_menu from_level to_level extra_inactive extra_active template &#39;&#39; &#39;&#39; child %}
            &lt;/ul&gt;
        {% endif %}
    &lt;/li&gt;

{% endfor %}

huangapple
  • 本文由 发表于 2020年1月6日 23:11:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/59614500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定