一级动态菜单的功能

动态菜单 一级菜单的实现:

1.先解释一下权限:

       首先我们要知道,我们是根据权限,来决定当前这个用户可以做什么样的操作。那么问题来了, 我要如何在 页面上展示, 不同的用户访问时, 他有哪些可以操作的按钮。

比如: CEO来的时候,他可以做任何事情。那么我就需要把所有的 按钮给他展示出来。
  可以添加,可以查看,可以编辑,可以修改。 那么最少就需要4个按钮。

  销售专员,登录的时候。 他只有 查看,和添加的功能。 那么我就只需要给他展示两个按钮。

2.然后再说一说菜单:

  菜单是一个可以点击之后,我能够看到,这个菜单下 拥有哪些功能。  或者哪些 二级菜单。
菜单是一个 有标题 有 url 的这个一个按钮。 那么我们的权限表 也是这样的结构。 但是还有一个问题,我们的权限表中有哪些记录(也就是哪些url 可以当作菜单使用)。
  客户列表 毋庸置疑,这个可以用来当作一个菜单。 添加客户也可以当作一个菜单(当然也可以将他当作 客户列表菜单下的一个功能)。  编辑和删除,就不能作为一个菜单。  因为编辑和删除都是 要对一个指定的客户进行操作了。  如果作为菜单使用,我们就需要在菜单下面,把所有的客户全部都列出来。 这么做太傻了。

我们要的应该是这样一个效果 说再多也不如一张图实在 上图:

这是一张整体的效果图, 信息管理是一级菜单。他没有URL。只是用来区分不同功能的二级菜单。客户列表和账单列表就是二级菜单了。二级菜单就有URL了,我这里都是查看页面的URL作为二级菜单:

 3. OK 效果大概是这样, 那么我们要怎么去实现:

  3.1  修改我们的权限表, 添加两个字段。  这个字段用来表示  我这条记录(url) 是否可以被当作,权限使用。(我们把这个功能搞成由使用者来决定), 另一个就是图标了。

class Permission(models.Model):
    """
    权限表
    """
    title = models.CharField(verbose_name='标题', max_length=32)
    url = models.CharField(verbose_name='含正则的URL', max_length=128)
    is_menu = models.BooleanField(verbose_name="是否可作为菜单", default=False)
    # 默认为False 因为菜单少, 功能多。
    icon = models.CharField(verbose_name="图标", max_length=32, null=True, blank=True)

    def __str__(self):
        return self.title

不要好奇,为什么图标是CharField。 因为我想使用 http://fontawesome.dashgame.com/ 这个网站的图标库。  只需要为标签添加一个 类。 就能拥有丰富的图标。 简单实用为啥不用。
而且 只是需要下载一下,他的css框架, 并放到我们的static中, 最后再模板里面引入一下就ok。

<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/>

  3.2  登录的步骤,添加一个session记录。  这个记录保存  当前这个用户拥有的权限当中,可以被当作菜单来使用的 这条url

因为我是开发rbac组件,所以添加session。 当然还是要着这个组件里完成喽。毕竟 web业务的 login视图,只是调用一下:上代码

 1 from django.conf import settings
 2 
 3 
 4 def init_permission(current_user, request):
 5     '''
 6     :param current_user: 当前请求 用户对象
 7     :param request:  当前请求 数据
 8     :return:
 9     '''
10     # 2. 权限 初始化
11     # 根据当前用户信息,获取当前用户所拥有的所有的权限(queryset对象 是不能直接放入,session中的)
12     permission_queryset = current_user.roles.filter(permissions__isnull=False) 
13         .values("permissions__url", "permissions__is_menu", "permissions__title", "permissions__icon") 
14         .distinct()
15 
16     # 获取权限 和 菜单信息。  权限放在权限列表,菜单放在菜单列表
17     menu_list = []
18     permission_list = []
19     for item in permission_queryset:
20         permission_list.append(item.get("permissions__url"))
21         if item.get("permissions__is_menu"):
22             temp = {
23                 "title": item.get("permissions__title"),  # 标题
24                 "icon": item.get("permissions__icon"),  # 图标
25                 "permissions__url": item.get("permissions__url"),  # 对应的跳转url
26             }
27             menu_list.append(temp)
28     request.session[settings.PERMISSIONS_SESSION_KEY] = permission_list
29     request.session[settings.MENU_SESSION_KEY] = menu_list
rbacserviceinit_permission.py

这里因为 又多了一个要添加到session中的数据。 但是循环遍历的还是原来的数据。所以做一点小优化。一次遍历,取出所有的url  和 可用作菜单的url。
我这里用字典是因为,要进行模板渲染的时候,比较方便。


  3.3  然后就是,从session中取出,权限列表,进行验证。菜单列表,进行渲染菜单的工作了。

 这里使用一个  inclusion_tag() 的,自定义模板语法的装饰器。 他的作用是 将被装饰函数的 返回值。传进模板中进行渲染,然后返回给调用者渲染完成的html字符串。
自定义模板语法的代码:

from django.template import Library
from django.conf import settings

register = Library()


@register.inclusion_tag("rbac/static_menu.html")
def static_menu(request):
    '''
    创建一级菜单
    :return:
    '''
    path_info = request.path_info
    menu_list = request.session.get(settings.MENU_SESSION_KEY)
    return {"menu_list": menu_list, "path_info": path_info}
rbac emplatetags bac_tags.py
<div class="static-menu">
    {% for menu in menu_list %}
        {% if path_info == menu.permissions__url %}
            <a href="{{ menu.permissions__url }}" class="active">
                <span class="icon-wrap"><i class="fa {{ menu.icon }}"></i></span>{{ menu.title }}</a>
        {% else %}
            <a href="{{ menu.permissions__url }}">
                <span class="icon-wrap"><i class="fa {{ menu.icon }}"></i></span>{{ menu.title }}</a>
        {% endif %}
    {% endfor %}
</div>
rbac emplates bacstatic_menu.html

OK  模板语法已经搞定了。  如何使用呢:
直接到我的业务app中,调用这个 模板就可以。传入相应的参数。

{% load rbac_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/>
    <title>Title</title>
</head>
<body>
    <div class="left-menu">
        <div class="menu-body">
            {% static_menu request%}
        </div>
    </div>
</body>
</html>
<--我这里只是为了 简洁,所以只是展示一下,使用的方法-->
<-- 在我调用{% static_menu request%} 的地方。 传入request参数。最终返回的就是已经 渲染好了的 html字符串-->
web emplateslayout.html
原文地址:https://www.cnblogs.com/chengege/p/10697383.html