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动态渲染多层菜单的主要内容,如果未能解决你的问题,请参考以下文章
2021-11-22 WinFrom面试题 实现一个能动态添加多层次结构的TreeView节点的递归方法(以菜单数据为例)