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 = '用户管理'
View Code

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
         }]
View Code

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')
                    })
View Code

4. 为了使两个列表(session中作为值)在session中对应的键的名字可以由用户改变,在名字中设置两个常量

settings.py文件:

# 存放权限的session的key
PERMISSION_SESSION_KEY = 'permission'

# 存放菜单的session的key
MENU_SESSION_KEY = 'menu'
View Code

5. 将两个列表放到session中

登录函数,第三步后面

from django.conf import settings
request.session[settings.PERMISSION_SESSION_KEY] = permission
request.session[settings.MENU_SESSION_KEY] = menu
View Code

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
View Code

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'
    }]
View Code

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>
View Code

9.将incluesion_tags应用到前端html页面中

<div class="left-menu">
<div class="menu-body">
{% load my_tags %} # my_tags为存放menu函数的文件名,
{% menu request %} # request为第七步中的menu函数的参数
</div>
</div>
View Code

注意:tags文件都放在templatetags目录中,目录名字不能变,位置随意。

目录分布

 

猜你喜欢

转载自www.cnblogs.com/kindvampire/p/12173299.html