Django CMS 多级下拉菜单 [英] Django CMS Multi-Level Dropdown Menu

查看:25
本文介绍了Django CMS 多级下拉菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Django CMS 有点陌生,我尽力避免询问,但这让我发疯.我制作了一个带有主题和类别模型的 Wiki 应用程序.我将它连接到我的 CMS 上的一个站点并将其添加到我的菜单中.现在我希望能够显示所有顶级类别,他们的子类别和;我的菜单上的主题以及这些主题的子类别等等.

菜单/导航应如下所示:维基类别1类别1.1话题类别1.2话题类别2话题类别3...现在我只能显示顶级类别:维基类别1类别2类别3

我已经创建了一个 menu.py 来获取我的 Wiki 上的自定义子菜单(您在上面看到的那个):

menu.py类 WikiSubMenu(CMSAttachMenu):name = _("维基子菜单")def get_nodes(self, request):节点 = []category = Category.objects.filter(parent_id__isnull=True)对于类别中的 c:节点 = 导航节点(标记安全(c.name),c.get_absolute_url(),c.id,)节点.附加(节点)返回节点menu_pool.register_menu(WikiSubMenu)

我的类别模型:

class Category(models.Model):''' 类别模型.'''name = models.CharField(max_length=100)slug = models.SlugField(unique=True)描述 = 模型.文本字段(空白 = 真)父 = 模型.外键('自己',空=真,空白=真,related_name='儿童')sort = models.IntegerField(默认= 0)元类:排序 = ['排序','名称']def __unicode__(self):返回 self.name@models.permalinkdef get_absolute_url(self):return ('topics:categories_category_detail', (), {'slug': self.slug})def get_all_children(self):返回 Category.objects.filter(parent=self)

现在,是否可以为所有带有子项、子项和子项等的类别创建一个子子菜单?

感谢您的帮助 &抱歉英语不好

-- --

我刚刚发现:

docs.django-cms.org/en/3.0.6/extending_cms/app_integration.html#integration-modifiers

(删除直接链接以添加 2 个新链接,抱歉)

我想这就是我要找的,我有点瞎,没找到.我会尝试一下,如果成功,我会发布答案.

-- 编辑(再次):--

修改器对我不起作用,但我得到了更进一步的,我再次阅读了 Docs,并发现我可以给 NavigationNodes 一个可选的 attr 字典,我用 parent=c 填充所有类别,这样我就有了我需要的数据,然后我发现它真的很好 引导下拉菜单,这正是我想要的.所以我的代码直到现在看起来像这样:

menu.py类主题子菜单(CMSAttachMenu):name = _("维基子菜单")def get_nodes(self, request):节点 = []category = Category.objects.filter(parent_id__isnull=True)对于类别中的 c:节点 = 导航节点(标记安全(c.name),c.get_absolute_url(),c.pk,属性=字典(subcategories=Category.objects.filter(parent=c),),)节点.附加(节点)返回节点

还有我的模板:

menu.html{% for child in children %}<li>{% if child.children %}<a class="dropdown-toggle" data-toggle="dropdown" href="#">{{ child.get_menu_title }}<span class="caret"></span></a><ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">{% for child in child.children %}{% if child.attr.subcategories.count %}
  • <a tabindex="-1" href="#">{{ child.get_menu_title }}</a><ul class="下拉菜单">{% for child.attr.subcategories %}<li><a tabindex="-1" href="{{ subcategory.get_absolute_url }}">{{ subcategory }}</a>
  • {% 结束为 %}{% 别的 %}<li><a href="{{child.get_absolute_url}}">{{ child.get_menu_title }}</li></a>{% 万一 %}{% 结束为 %}{% 别的 %}<a href="{{ child.get_absolute_url }}"><跨度>{{ child.get_menu_title }}</span></a>{% 万一 %}{% if class 和 forloop.last 而不是 forloop.parentloop %}{% 万一 %}{% 结束为 %}

    我的下一步是将模板中的整个for"循环写入方法中,使用 while 循环或其他方法使其递归,并将结果作为答案发布.

    我希望我能帮助那些人:)

    解决方案

    WOHO!我终于做到了!

    base.html

    menu.html:

    {% for child in children %}<li class="child{% if child.selected %} selected{% endif %}{% if child.ancestor %}祖先{% endif %}{% if child.sibling %}兄弟{% endif %}{% if child.descendant %}后代{% endif %}{% if child.children %} dropdown{% endif %}"><a {% if child.children %}class="dropdown-toggle" data-toggle="dropdown"{% endif %} href="{{ child.attr.redirect_url|default:child.get_absolute_url }}"><span>{{ child.get_menu_title }}</span>{% if child.children|length %}<span class="caret"></span>{% endif %}</a>{% if child.children %}<ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">{% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}{% 万一 %}{% if class 和 forloop.last 而不是 forloop.parentloop %}{% endif %}{% 结束为 %}

    和我的下拉菜单.html:(递归的东西从这里开始)

    {% 加载 i18n menu_tags 缓存 mptt_tags %}{% for child in children %}<li {% if child.children %}class="dropdown-submenu"{% else %} {% endif %}><a tabindex="-1" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}</a>{% if child.children %}<ul class="下拉菜单">{% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}{% 万一 %}{% 结束为 %}

    还有最重要的,menu.py:

    class TopicsSubMenu(CMSAttachMenu):name = _("维基子菜单")def get_nodes(self, request):节点 = []类别 = Category.objects.all()对于类别中的 c:节点 = 导航节点(标记安全(c.name),c.get_absolute_url(),c.pk)如果 c.parent:node.parent_id = c.parent_id节点.附加(节点)主题 = Topic.objects.all().exclude(category__isnull=True)对于主题中的 t:节点 = 导航节点(标记安全(t.title),t.get_absolute_url(),t.pk,t.category.all()[0].id,parent_namespace="TopicsSubMenu")节点.附加(节点)返回节点menu_pool.register_menu(TopicsSubMenu)

    就是这样!

    Im kinda new to Django CMS and im trying my best to avoid asking, but this one drives me crazy. I made a Wiki app with a Topic, and Category model. I hooked it to a Site on my CMS and added it to my Menu. Now i would like to be able to show all Top-Level categories, their Child Categories & Topics, and the Child categories of these, and so on, on my menu.

    Menu/Navigation should look like this:
    
    Wiki
        Category1
            Category1.1
                Topic
            Category1.2
            Topic
        Category2
            Topic
        Category3
            ...
    
    Right now i can only show the Top categories:
    
    Wiki
        Category1
        Category2
        Category3
    

    I Already created a menu.py to get a Custom SubMenu on my Wiki (the one you see above):

    menu.py
    
    class WikiSubMenu(CMSAttachMenu):
        name = _("Wiki Sub-Menu")
    
        def get_nodes(self, request):
            nodes = []
            categories = Category.objects.filter(parent_id__isnull=True)
    
            for c in categories:
                node = NavigationNode(
                    mark_safe(c.name),
                    c.get_absolute_url(),
                    c.id,
    
                )
    
                nodes.append(node)
    
            return nodes
    
    menu_pool.register_menu(WikiSubMenu)
    

    My Category Model:

    class Category(models.Model):
        ''' Category model. '''
        name = models.CharField(max_length=100)
        slug = models.SlugField(unique=True)
        description = models.TextField(blank=True)
        parent = models.ForeignKey(
            'self',
            null=True,
            blank=True,
            related_name='children'
        )
        sort = models.IntegerField(default=0)
    
        class Meta:
            ordering = ['sort', 'name']
    
        def __unicode__(self):
            return self.name
    
        @models.permalink
        def get_absolute_url(self):
            return ('topics:categories_category_detail', (), {'slug': self.slug})
    
        def get_all_children(self):
            return Category.objects.filter(parent=self)
    

    Now, is it possible to create a Sub-SubMenu, for all Categories with Childs, and their Childs, and their Childs, and so on?

    Thanks for help & sorry for bad english

    -- EDIT : --

    I just found that:

    docs.django-cms.org/en/3.0.6/extending_cms/app_integration.html#integration-modifiers

    (Removed direct link to add 2 new Links, sorry for that)

    I think that is what im looking for, i was kinda blind that i didn't found it. I'll try it out and Post the Answer if it worked out.

    -- EDIT (AGAIN): --

    The modifier didn't worked for me, but i got a whole piece further, i read the Docs again, and found that i can give the NavigationNodes an optional attr dictonary, which i filled with all Categories with parent=c, on that way i had the data i needed, then i found that real nice bootstrap dropdown menu, that does exacly what i wanted. So my code until now looks like that:

    menu.py
    
    class TopicsSubMenu(CMSAttachMenu):
        name = _("Wiki Sub-Menu")
    
        def get_nodes(self, request):
            nodes = []
            categories = Category.objects.filter(parent_id__isnull=True)
    
            for c in categories:
                node = NavigationNode(
                    mark_safe(c.name),
                    c.get_absolute_url(),
                    c.pk,
                    attr=dict(
                        subcategories=Category.objects.filter(parent=c),),
                )
    
                nodes.append(node)
            return nodes
    

    And my Template:

    menu.html
    
    {% for child in children %}
        <li>
            {% if child.children %}
    
                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                    {{ child.get_menu_title }}
                    <span class="caret">
                    </span>
                </a>
                <ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">
                    {% for child in child.children %}
                        {% if child.attr.subcategories.count %}
                            <li class="dropdown-submenu">
                                <a tabindex="-1" href="#">{{ child.get_menu_title }}</a>
                                <ul class="dropdown-menu">
                                    {% for subcategory in child.attr.subcategories %}
                                    <li>
                                        <a tabindex="-1" href="{{ subcategory.get_absolute_url }}">{{ subcategory }}</a>
                                    </li>
                                    {% endfor %}
                                </ul>
    
    
                            </li>
                        {% else %}
                        <li><a href="{{child.get_absolute_url}}">{{ child.get_menu_title }}</li></a>
                        {% endif %}
                    {% endfor %}
    
                </ul>
            {% else %}
                <a href="{{ child.get_absolute_url }}">
                    <span>
                        {{ child.get_menu_title }}
                    </span>
                </a>
            {% endif %}
        </li>
    
        {% if class and forloop.last and not forloop.parentloop %}
        {% endif %}
    
    
    {% endfor %}
    

    My next step will be to write the whole "for" loops from the template in a Method, make it recursive with a while loop or something and post the result as Answer.

    I hope i can help someone with that stuff :)

    解决方案

    WOHO! I finally did it!

    base.html

    <div class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
            {% show_menu 0 100 100 100 "menu.html" %}
        </ul>
    </div>
    

    menu.html:

    {% 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 %}{% if child.children %} dropdown{% endif %}">
    
            <a {% if child.children %}class="dropdown-toggle" data-toggle="dropdown"{% endif %} href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">
                <span>{{ child.get_menu_title }}</span>{% if child.children|length %}<span class="caret"></span>{% endif %}
            </a>
    
            {% if child.children %}
                <ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">
                    {% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}
                </ul>
            {% endif %}
    
        </li>
        {% if class and forloop.last and not forloop.parentloop %}{% endif %}
    
    {% endfor %}
    

    and my dropdownmenu.html: (The recursive stuff starts here)

    {% load i18n menu_tags cache mptt_tags %}
    {% for child in children %}
        <li {% if child.children %}class="dropdown-submenu"{% else %} {% endif %}>
            <a tabindex="-1" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}</a>
            {% if child.children %}
                <ul class="dropdown-menu">
                    {% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}
                </ul>
            {% endif %}
    
        </li>
    {% endfor %}
    

    and the most important, menu.py:

    class TopicsSubMenu(CMSAttachMenu):
        name = _("Wiki Sub-Menu")
    
        def get_nodes(self, request):
            nodes = []
            categories = Category.objects.all()
    
            for c in categories:
                node = NavigationNode(
                    mark_safe(c.name),
                    c.get_absolute_url(),
                    c.pk
                )
                if c.parent:
                    node.parent_id = c.parent_id
                nodes.append(node)
    
            topics = Topic.objects.all().exclude(category__isnull=True)
            for t in topics:
                node = NavigationNode(
                    mark_safe(t.title),
                    t.get_absolute_url(),
                    t.pk,
                    t.category.all()[0].id,
                    parent_namespace="TopicsSubMenu"
                )
                nodes.append(node)
            return nodes
    
    menu_pool.register_menu(TopicsSubMenu)
    

    And thats it!

    这篇关于Django CMS 多级下拉菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆