Django动态渲染多层菜单

Posted 曾春云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django动态渲染多层菜单相关的知识,希望对你有一定的参考价值。

 

为后续给菜单设置权限管理方便,通过给页面模版菜单动态渲染,通过数据菜单表进行匹配需要渲染的菜单

 1 #Django表结构
 2 
 3 class Menus(models.Model):
 4 
 5     name = models.CharField(max_length=32, verbose_name=u菜单名)
 6     parent = models.ForeignKey(self,
 7                                verbose_name=u父级菜单,
 8                                null=True,
 9                                blank=True,
10                                default=0,
11                                help_text=u如果添加的是子菜单,请选择父菜单)
12     show = models.BooleanField(verbose_name=u是否显示,
13                                default=False,
14                                help_text=u菜单是否显示,默认添加不显示)
15     url = models.CharField(max_length=300,
16                            verbose_name=u菜单url地址,
17                            null=True,
18                            blank=True,
19                            default=javascript:void(0),
20                            help_text=u是否给菜单设置一个url地址)
21     priority = models.IntegerField(verbose_name=u显示优先级,
22                                    null=True,
23                                    blank=True,
24                                    default=-1,
25                                    help_text=u菜单的显示顺序,优先级越大显示越靠前)
26     permission_id = models.IntegerField(verbose_name=u权限编号,
27                                         help_text=u给菜单设置一个编号,用于权限控制,
28                                         error_messages={field-permission_id: u只能输入数字})
29 
30     def __str__(self):
31         return "{parent}{name}".format(name=self.name, parent="%s-->" % self.parent.name if self.parent else ‘‘)
32 
33     class Meta:
34         verbose_name = u"菜单"
35         verbose_name_plural = u"菜单"
36         ordering = ["-priority", "id"]
 1 #admin.py
 2 
 3 from django.contrib import admin
 4 
 5 # Register your models here.
 6 
 7 from cloud.api import models as api_models
 8 
 9 
10 class MenusAdmin(admin.ModelAdmin):
11     ordering = (-parent,)
12     list_filter = (name,)
13     list_display = [name, parent, show, url, priority, permission_id]
14     fields = [name, parent, show, url, priority, permission_id]
15 
16 admin.site.register(api_models.Menus, MenusAdmin)
#  模版中件件,用于在页面返回且将菜单渲染出来

def make_menus_html(menus, parent_id=None, current_parent_id=None, active=None):
    """
    menus = Menus.objects.all()
    :param menus: 寻找的对象,传一个queryset对象
    :param parent_id: 父级菜单ID
    :param current_parent_id: 当前父级菜单ID
    :param active: 激活的菜单名
    :return:
    """
    make_html = ""
    for menu in menus:
        child_menu_flag = "treeview"
        menu_right_flag = <span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span>
        child_menu = <li><a href="{menu_url}"><i class="fa fa-circle-o"></i> {menu_name}</a></li>
        child_menu_html = <ul class="treeview-menu">{make_child_menu_html}</ul>
        master_menu_html = """
        <li class="{child_menu_flag} {active}">
            <a href="{menu_url}"><i class="fa {menu_icon}"></i> <span>{menu_name}</span>{menu_right_flag}</a>
            <ul class="treeview-menu">
            {children_menu_html}
            </ul>
        </li>"""
        children_menu_html = """
        <li class="treeview">
            <a href="{menu_url}"><i class="fa fa-circle-o"></i> <span>{menu_name}</span>{menu_right_flag}</a>
            {child_menu_html}
        </li>"""
        parent = menu.parent  # 获取当前菜单的父级菜单
        if current_parent_id == menu.id or (not parent and current_parent_id):
            continue  # 如果当前父级菜单ID是自己或没有父级菜单且有当前父级ID则跳过本次循环
        if not parent and current_parent_id is None:  # 如果没有父级菜单且当前父级ID是None
            make_children_menu_html = make_menus_html(menus, parent_id=parent_id, current_parent_id=menu.id)
            if not make_children_menu_html:
                menu_right_flag = ‘‘
            menu_icon = "fa-eye"
            if hasattr(menu, icon_name):
                menu_icon = menu.icon_name
            if menu.name == active:
                active_menu = active
            else:
                active_menu = ‘‘
            make_master_menu_html = master_menu_html.format(child_menu_flag=child_menu_flag,
                                                            active=active_menu,
                                                            menu_url=menu.url,
                                                            menu_icon=menu_icon,
                                                            menu_name=menu.name,
                                                            menu_right_flag=menu_right_flag,
                                                            children_menu_html=make_children_menu_html)
            make_html += make_master_menu_html
        elif parent and current_parent_id == parent.id:  # 如果有父级且当前父级ID是自己的父级ID
            make_child_menu_html = make_menus_html(menus, parent_id=current_parent_id, current_parent_id=menu.id)
            if make_child_menu_html:
                child_menu_html = child_menu_html.format(make_child_menu_html=make_child_menu_html)
                children_menu_html = children_menu_html.format(menu_url=menu.url,
                                                               menu_name=menu.name,
                                                               menu_right_flag=menu_right_flag,
                                                               child_menu_html=child_menu_html)
            else:
                children_menu_html = child_menu.format(menu_url=menu.url, menu_name=menu.name)
            make_html += children_menu_html
        else:
            continue
    return make_html


def make_menus_processor(request):
    menus_obj = Menus.objects.all()
    menus = make_menus_html(menus=menus_obj, active="监控")
    return {menus: format_html(menus)}

 

 

然后通过Django  admin后台添加菜单数据,即可实现层叠动态可折叠菜单,该样式模版基于一个开源的管理模版

https://github.com/almasaeed2010/AdminLTE

以上是关于Django动态渲染多层菜单的主要内容,如果未能解决你的问题,请参考以下文章

JS使用Vue自定义组件实现动态多层数据渲染+递归+踩坑

JS使用Vue自定义组件实现动态多层数据渲染+递归+踩坑

Android - 导航抽屉 - 与动态菜单项重叠的片段

python django 业务树形结构规划及页面渲染

java Ftp上传创建多层文件的代码片段

2021-11-22 WinFrom面试题 实现一个能动态添加多层次结构的TreeView节点的递归方法(以菜单数据为例)