Django之一级菜单
Posted kindvampire
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之一级菜单相关的知识,希望对你有一定的参考价值。
1.model设计
from django.db import models class Permission(models.Model): url = models.CharField(max_length=64, verbose_name=‘权限‘) title = models.CharField(max_length=32, verbose_name=‘标题‘) # 备注这个url是做什么的 icon = models.CharField(max_length=64, null=True, verbose_name=‘图标‘) # 存放菜单前面的图标 is_menu = models.BooleanField(default=False) # 用来判断(此url)是否是菜单 def __str__(self): return self.title class Meta: verbose_name_plural = ‘权限管理‘ class Role(models.Model): name = models.CharField(max_length=32, verbose_name=‘角色‘) permissions = models.ManyToManyField(Permission, verbose_name=‘角色拥有的权限‘, blank=True) def __str__(self): return self.name class Meta: verbose_name_plural = ‘角色管理‘ class User(models.Model): username = models.CharField(max_length=32, verbose_name=‘用户名‘,unique=True) password = models.CharField(max_length=32, verbose_name=‘密码‘) roles = models.ManyToManyField(Role, verbose_name=‘用户的角色‘, blank=True) def __str__(self): return self.username class Meta: verbose_name_plural = ‘用户管理‘
2. views.py文件 登录函数中登陆成功后获取当前用户的权限的所有信息(url,title,icon,is_menu)
如:
per = obj.roles.all().filter(permissions__url__isnull=False).values(‘permissions__url‘, ‘permissions__title‘, ‘permissions__icon‘, ‘permissions__is_menu‘, ).distinct() print(per) ## 打印per的数据 QuerySet[{ ‘permissions__url‘: ‘/customer/list/‘, ‘permissions__title‘: ‘客户列表‘, ‘permissions__icon‘: ‘fa-connectdevelop‘, ‘permissions__is_menu‘: True}, { ‘permissions__url‘: ‘/customer/add/‘, ‘permissions__title‘: ‘添加客户‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False}, { ‘permissions__url‘: ‘/customer/edit/(?P<cid>d+)/‘, ‘permissions__title‘: ‘编辑客户‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False}, { ‘permissions__url‘: ‘/customer/del/(?P<cid>d+)/‘, ‘permissions__title‘: ‘删除客户‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False}, { ‘permissions__url‘: ‘/payment/list/‘, ‘permissions__title‘: ‘账单列表‘, ‘permissions__icon‘: ‘fa-code-fork‘, ‘permissions__is_menu‘: True}, { ‘permissions__url‘: ‘/payment/add/‘, ‘permissions__title‘: ‘添加账单‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False}, { ‘permissions__url‘: ‘/payment/edit/(?P<pid>d+)/‘, ‘permissions__title‘: ‘编辑账单‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False}, { ‘permissions__url‘: ‘/payment/del/(?P<pid>d+)/‘, ‘permissions__title‘: ‘删除账单‘, ‘permissions__icon‘: None, ‘permissions__is_menu‘: False }]
3、从上述中的数据中挑出菜单列表
# 菜单列表 menu = [] # 权限列表 permission = [] for i in per: permission.append({ ‘url‘: i.get(‘permissions__url‘) }) if i.get(‘permissions__is_menu‘): # 如果permissions__is_menu为True就是菜单,放到菜单列表中 menu.append({ ‘url‘: i.get(‘permissions__url‘), ‘title‘: i.get(‘permissions__title‘), ‘icon‘: i.get(‘permissions__icon‘) })
4. 为了使两个列表(session中作为值)在session中对应的键的名字可以由用户改变,在名字中设置两个常量
settings.py文件:
# 存放权限的session的key PERMISSION_SESSION_KEY = ‘permission‘ # 存放菜单的session的key MENU_SESSION_KEY = ‘menu‘
5. 将两个列表放到session中
登录函数,第三步后面
from django.conf import settings request.session[settings.PERMISSION_SESSION_KEY] = permission request.session[settings.MENU_SESSION_KEY] = menu
6. 权限验证的中间件中获取session中的PERMISSION_SESSION_KEY进行权限验证
permission = request.session.get(settings.PERMISSION_SESSION_KEY) # 权限验证(url,中间件中获取的当前url地址如:通过request.path_info获取) for i in permission: if re.match(r‘^{}$‘.format(i[‘url‘]), url): return
7. incluesion_tags(模板中调用函数)
目的:用于前端菜单的展示而编写的函数
函数作用:为菜单添加样式,然后通过装饰器交给特定的模板,
具体如下:
my_tags.py文件
# -*- coding: utf-8 -*- # __author__ = "maple" from django import template from django.conf import settings import re register = template.Library() @register.inclusion_tag(‘menu_tag.html‘) # 讲给这个模板进行渲染 def menu(request): url = request.path_info # 获取当前url地址 menu_list = request.session[settings.MENU_SESSION_KEY] # 获取session中的菜单url地址 # 添加激活的样式 for i in menu_list: if re.match(f‘^{i["url"]}$‘,url): # 判断,如果当前页面地址栏中的url地址是菜单中的地址 i[‘class‘] = ‘active‘ # 就给菜单中的地址加上active类选择器。 break return {‘menu_list‘:menu_list} #此时,menu_list列表中的数据为:(前端页面当前停留在客户列表菜单上) [{ ‘url‘: ‘/customer/list/‘, ‘title‘: ‘客户列表‘, ‘icon‘: ‘fa-connectdevelop‘, ‘class‘: ‘active‘}, { ‘url‘: ‘/payment/list/‘, ‘title‘: ‘账单列表‘, ‘icon‘: ‘fa-code-fork‘ }]
8. menu_tag.html 渲染模板
<div class="static-menu"> {% for menu in menu_list %} <a href="{{ menu.url}}" class="{{menu.class}}"> <span class="icon-wrap"><i class="fa {{menu.icon}}"></i></span> {{ menu.title}}</a> {% endfor %} </div>
9.将incluesion_tags应用到前端html页面中
<div class="left-menu"> <div class="menu-body"> {% load my_tags %} # my_tags为存放menu函数的文件名, {% menu request %} # request为第七步中的menu函数的参数 </div> </div>
注意:tags文件都放在templatetags目录中,目录名字不能变,位置随意。
目录分布
以上是关于Django之一级菜单的主要内容,如果未能解决你的问题,请参考以下文章
Django表示错误:选择一个有效的选择。这种选择不是可用的选择之一
如何在 Django Summernote 中显示编程片段的代码块?