django-simpleui自定义菜单权限
效果图↓
需要配置↓
index.html↓
<!DOCTYPE html> {% load i18n static %} {% load simpletags %} {% load customtags %} {% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %} <!-- The project use: django-simpleui source code: https://github.com/newpanjing/simpleui --> <html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}> <head> <meta charset="UTF-8"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/> {% block title %} <title>{{ site_title }}</title> {% endblock %} {% block icon %} {% endblock %} {% block css %} {% include 'admin/includes/css-part.html' %} <link rel="stylesheet" href="{% static 'admin/simpleui-x/css/index.css' %}?_=3.2"> <link rel="stylesheet" href="{% static 'admin/simpleui-x/waves/waves.min.css' %}?_=2.1"> {% endblock %} {% block head %} {% endblock %} </head> <body> <style type="text/css"> .el-tabs__nav .el-tabs__item:nth-child(1) .el-icon-close { display: none; } * { -webkit-overflow-scrolling: touch; } [v-block] { display: none; } </style> {% verbatim dynamicCss %} {% endverbatim dynamicCss %} {% block menus %} {% autoescape off %} {% custom_menus %} {% endautoescape %} {% endblock %} <div id="main" @click="mainClick($event)" v-block> {% block theme_css %} <link v-if="theme && theme!=''" rel="stylesheet" :href="theme"> {% if "SIMPLEUI_DEFAULT_THEME"|get_config %} <link v-else rel="stylesheet" href="{% static 'admin/simpleui-x/theme/' %}{{ "SIMPLEUI_DEFAULT_THEME"|get_config }}"> {% endif %} {% endblock %} <!-- mobile --> <el-drawer class="lite-menus" title="{{ site_header }}" :visible.sync="drawer" :show-close="false" size="50%" direction="ltr"> <el-menu unique-opened="true" :default-active="menuActive"> <div v-for="(item,i) in menus" :key="item"> <el-menu-item v-if="!item.models" :index="item.eid+''" @click="openTab(item,item.eid)"> <i :class="item.icon"></i> <span slot="title" v-text="item.name"></span> </el-menu-item> <el-submenu v-else :index="item.eid+''"> <template slot="title"> <i :class="item.icon"></i> <span slot="title" v-text="item.name"></span> </template> <el-menu-item-group v-for="(sub,j) in item.models" :title="sub.name" :key="sub.name"> <el-menu-item :index="sub.eid+''" @click="openTab(sub,item.eid)"> <i :class="sub.icon"></i> <span slot="title" v-text="sub.name"></span> </el-menu-item> </el-menu-item-group> </el-submenu> </div> </el-menu> </el-drawer> <el-container :style="{height: height+'px'}"> <el-aside v-show="!mobile" width="auto" class="menu" {% block menu_style %}{% endblock %}> {% block logo %} <div class="logo-wrap" v-if="!fold"> <div class="float-wrap"> <div class="left"> {% if "SIMPLEUI_LOGO"|get_config %} <img src="{{ "SIMPLEUI_LOGO"|get_config |safe }}"> {% else %} <img src="{% static 'admin/simpleui-x/img/logo.png' %}"> {% endif %} </div> <div class="left"> <span>{{ site_header }}</span> </div> </div> </div> {% endblock %} <!-- menu --> <transition name="el-zoom-in-center"> <multiple-menu :menus="menus" :menu-active="menuActive" :fold="fold" ></multiple-menu> </transition> </el-aside> <el-container> {% block header %} <el-header class="navbar" style="font-size: 12px;padding: 10px;height: auto"> <div class="float-wrap"> <div class="left"> <el-button v-waves circle icon="fas fa-bars" style="margin-right: 10px;border: none" @click="foldClick()"></el-button> {% block breadcrumb %} <el-breadcrumb v-if="!mobile" style="display: inline-block;" separator="/"> {% verbatim myclode %} <el-breadcrumb-item><i :class="menus[0].icon" :key="menus[0].name"></i>{{ menus[0].name }} </el-breadcrumb-item> <el-breadcrumb-item v-for="item in breadcrumbs" :key="item"> <span :class="getIcon(item.name,item.icon)"></span> <span v-text="item.name"></span> </el-breadcrumb-item> {% endverbatim myclode %} </el-breadcrumb> {% endblock %} </div> <div class="right"> <el-button icon="fas fa-font" circle v-waves @click="fontClick()"></el-button> <el-button :icon="this.zoom?'fas fa-compress-arrows-alt':'fas fa-expand-arrows-alt'" @click="goZoom()" circle></el-button> <el-button icon="fas fa-home" @click="goIndex('{{ 'SIMPLEUI_INDEX'|get_config }}')" circle v-waves></el-button> {% verbatim mycode %} <el-button @click="themeDialogVisible=true" v-waves> <i class="fas fa-palette"></i> <span v-text="getLanuage('Change theme')"></span><i class="el-icon-arrow-down el-icon--right"></i> </el-button> {% endverbatim mycode %} <el-dropdown> <el-button v-waves> <i class="fas fa-user"></i> {{ user }}<i class="el-icon-arrow-down el-icon--right"></i> </el-button> <el-dropdown-menu slot="dropdown"> {% verbatim mycode %} <el-dropdown-item v-waves icon="far fa-edit" @click.native="changePassword()">{{ language.change_password }} </el-dropdown-item> {% endverbatim mycode %} {% has_enable_admindoc as has_admindoc %} {% if has_admindoc %} <el-dropdown-item icon="el-icon-document" @click.native="openTab({eid:100000,name:'{% trans 'Documentation' %}',icon:'el-icon-document',url:'{% url 'django-admindocs-docroot' %}'})" divided>{% trans 'Documentation' %}</el-dropdown-item> {% endif %} {% verbatim mycode %} <el-dropdown-item icon="el-icon-close" @click.native="logout()" divided>{{ language.logout }}</el-dropdown-item> {% endverbatim mycode %} </el-dropdown-menu> </el-dropdown> </div> </div> </el-header> {% endblock %} <el-main> <el-tabs v-model="tabModel" {% block tabs_type %}type="border-card" {% endblock %} editable :style="isResize?'height:100%':'height: calc(100% - 97px)'" @edit="handleTabsEdit" @tab-click="tabClick"> <el-tab-pane v-for="(item,index) in tabs" :closable="index!=0" :label="item.name" :name="item.id" :key="item.id" lazy="true"> {% home_page %} {% if home %} <span v-if="index==0" slot="label"><i class="{{ icon }}"></i><span>{{ title }}</span> </span> <span v-else slot="label" @contextmenu.prevent="contextmenu(item,$event)"> {% else %} <span slot="label" @contextmenu.prevent="contextmenu(item,$event)"> {% endif %} {% block tab-item %} <i :class="item.loading?'el-icon-loading':item.icon"></i> <span v-text="item.name"></span> {% endblock %} </span> <div v-if="index==0" style="height:100%"> {% block home_content %} {% if home %} <iframe :src="'{{ home }}'"></iframe> {% else %} {% include './home.html' %} {% endif %} {% endblock %} </div> <div v-else class="iframe-wrap"> <iframe :src="item.url" :id="item.id" @load="iframeLoad(item,$event)"></iframe> {% if "SIMPLEUI_LOADING"|get_config != False %} <div v-if="loading" class="loading" @dblclick="loading=false"> <div class="center"> <span class="el-icon-loading"></span> <span>loading...</span> </div> </div> {% endif %} </div> </el-tab-pane> </el-tabs> </el-main> </el-container> </el-container> <ul v-if="popup.show" class="el-dropdown-menu el-popper" ref="popupmenu" :style="{position: 'absolute',top: popup.top+'px',left: popup.left+'px'}" x-placement="top-end"> <li v-for="(item,index) in popup.menus" tabindex="-1" class="el-dropdown-menu__item" @click="item.handler(popup.tab,item)"><i :class="item.icon"></i><span v-text="item.text"></span> </li> </ul> <el-dialog title="{% trans 'Change password' %}" :visible.sync="pwdDialog.show"> <iframe frameborder="0" :src="pwdDialog.url" width="100%" height="500"></iframe> </el-dialog> {% block theme_dialog %} <el-dialog :title="getLanuage('Change theme')" :visible.sync="themeDialogVisible" :width="small?'90%':'50%'"> {% block theme_body %} <div class="change-theme clearfix"> <div v-waves :class="{'theme-item':true,active:themeName==item.text}" v-for="(item,i) in themes" :key="item.text" :title="getLanuage(item.text)" @click="setTheme(item)"> <div class="theme-menu" :style="{background:item.menu}"> <div class="theme-logo" :style="{background: item.logo}"></div> </div> <div class="theme-top" :style="{background: item.top}"></div> </div> </div> {% endblock %} </el-dialog> {% endblock %} {% block font_dialog %} <el-dialog :title="getLanuage('Set font size')" :visible.sync="fontDialogVisible" :width="small?'90%':'50%'"> <el-slider v-model="fontSlider" :min="12" :max="100" show-input @change="fontSlideChange"></el-slider> <div style="text-align: right;padding-top: 20px"> <el-button type="primary" @click="reset()" v-text="getLanuage('Reset')"></el-button> </div> </el-dialog> {% endblock %} </div> {% block base_script %} <script type="text/javascript"> {% if home %} var home = { id: '0', index: '1', name: '{{ title }}', icon: '{{ icon }}', active: true, eid: '1' } {% else %} var home = { id: '0', index: '1', eid: '1', name: "{% trans 'Home' %}", icon: 'fas fa-home' }; {% endif %} menus.unshift(home); window.language = { change_password: '{% trans 'Change password' %}', logout: '{% trans 'Log out' %}', yes: '{% trans 'Yes' %}', no: '{% trans 'No' %}', confirm: '{% trans 'Are you sure?' %}' } window.themeUrl = '{% static 'admin/simpleui-x/theme/' %}'; window.urls = { changePassword: "{% url 'admin:password_change' %}", logout: "{% url 'admin:logout' %}" } var lanuageCode = '{% get_language %}'; function localeError(e) { console.warn("Please add the {% get_language %}.js language file to the '/simpleui-x/theme' directory.") console.log("See simpleui i18n:https://github.com/newpanjing/simpleui/blob/master/i18n.md") console.log("或者加入QQ群:786576510 (Join QQ Group.)") } </script> {% include 'admin/includes/js-part.html' %} <script type="text/javascript"> __simpleui_version = '{% simple_version %}'; </script> <script type="text/javascript" src="{% static 'admin/simpleui-x/automatic/dicts.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/automatic/segment.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/locale/en-us.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/locale/' %}{% get_language %}.js?_={% get_version %}" onerror="localeError()"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/js/cookie.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/theme/theme.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/waves/waves.min.js' %}?_={% get_version %}"></script> {% block index_js %} <script type="text/javascript" src="{% static 'admin/simpleui-x/js/menu.js' %}?_={% get_version %}"></script> <script type="text/javascript" src="{% static 'admin/simpleui-x/js/index.js' %}?_={% get_version %}"></script> {% endblock %} {% block autoupdate %} {% endblock %} {% endblock %} {% load_analysis %} {% block script %} {# 预留脚本block 可以实现基础该页面,添加自定义脚本#} {% endblock %} </body> </html>
customtags↓
# -*- coding: utf-8 -*- import base64 import json import os import sys from django import template from django.core.serializers.json import DjangoJSONEncoder from django.utils.functional import Promise try: from django.utils.encoding import force_text except: from django.utils.encoding import force_str as force_text register = template.Library() PY_VER = sys.version[0] # 2 or 3 if PY_VER != '2': from importlib import reload from urllib.parse import parse_qsl else: from urlparse import parse_qsl class LazyEncoder(DjangoJSONEncoder): """ 解决json __proxy__ 问题 """ def default(self, obj): if isinstance(obj, Promise): return force_text(obj) return super(LazyEncoder, self).default(obj) def unicode_to_str(u, encoding='utf-8'): if PY_VER != '2': return u return u.encode(encoding) @register.filter def to_str(obj): return str(obj) def __get_config(name): from django.conf import settings value = os.environ.get(name, getattr(settings, name, None)) return value @register.filter def get_config(key): return __get_config(key) @register.simple_tag(takes_context=True) def custom_menus(context, _get_config=None): data = [] # print(context.request.user.has_perm("%s.%s" % (opts.app_label, codename)) if not _get_config: _get_config = get_config config = _get_config('SIMPLEUI_CONFIG') if not config: config = {} if config.get('dynamic', False) is True: config = _import_reload(_get_config('DJANGO_SETTINGS_MODULE')).SIMPLEUI_CONFIG app_list = context.get('app_list') for app in app_list: _models = [ { 'name': m.get('name'), 'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name'))), 'url': m.get('admin_url'), 'addUrl': m.get('add_url'), 'breadcrumbs': [{ 'name': app.get('name'), 'icon': get_icon(app.get('app_label'), app.get('name')) }, { 'name': m.get('name'), 'icon': get_icon(m.get('object_name'), unicode_to_str(m.get('name'))) }] } for m in app.get('models') ] if app.get('models') else [] module = { 'name': app.get('name'), 'icon': get_icon(app.get('app_label'), app.get('name')), 'models': _models } data.append(module) # 如果有menu 就读取,没有就调用系统的 key = 'system_keep' if config and 'menus' in config: if config.get(key, None): temp = config.get('menus') _temp = temp[:] for i in _temp: if 'models' not in i: if context.request.user.has_perm("%s.%s" % (i.get("name"), i.get("codename"))): i['breadcrumbs'] = [{ 'name': i.get('name'), 'icon': i.get('icon') }] else: temp.remove(i) else: _i = i.get('models')[:] for k in _i: if context.request.user.has_perm("%s.%s" % (k.get("name"), k.get("codename"))): k['breadcrumbs'] = [{ 'name': i.get('name'), 'icon': i.get('icon') }, { 'name': k.get('name'), 'icon': k.get('icon') }] else: i.get("models").remove(k) if not i.get("models"): temp.remove(i) for i in temp: data.append(i) else: data = config.get('menus') # 获取侧边栏排序, 如果设置了就按照设置的内容排序, 留空则表示默认排序以及全部显示 if config.get('menu_display') is not None: display_data = list() for _app in data: if _app['name'] not in config.get('menu_display'): continue _app['_weight'] = config.get('menu_display').index(_app['name']) display_data.append(_app) display_data.sort(key=lambda x: x['_weight']) data = display_data # 给每个菜单增加一个唯一标识,用于tab页判断 eid = 1000 handler_eid(data, eid) menus_string = json.dumps(data, cls=LazyEncoder) # 把data放入session中,其他地方可以调用 if not isinstance(context, dict) and context.request: context.request.session['_menus'] = menus_string return '<script type="text/javascript">var menus={}</script>'.format(menus_string) def handler_eid(data, eid): for i in data: eid += 1 i['eid'] = eid if 'models' in i: eid = handler_eid(i.get('models'), eid) return eid def get_icon(obj, name=None): temp = get_config_icon(name) if temp != '': return temp _dict = { 'auth': 'fas fa-shield-alt', 'User': 'far fa-user', 'Group': 'fas fa-users-cog' } temp = _dict.get(obj) if not temp: return 'far fa-circle' return temp # 从配置中读取图标 def get_config_icon(name): _config_icon = __get_config('SIMPLEUI_ICON') if _config_icon is None: return '' if name in _config_icon: return _config_icon.get(name) return '' def _import_reload(_modules): _obj = __import__(_modules, fromlist=_modules.split('.')) reload(_obj) return _obj
index.html路径一定要按照第三张截图所示配置,customtags.py文件可以放在任意APP目录下的templatetags目录下
本文来自博客园,作者:一石数字欠我15w!!!,转载请注明原文链接:https://www.cnblogs.com/52-qq/p/17351748.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
2022-04-25 xx
2018-04-25 Ubuntu16.04 下docker部署web项目
2018-04-25 jQuery实现啊城市选择
2018-04-25 城市代码-字典实现