動態多級菜單結合用戶權限生成菜單


完整代碼:

  1 import re
  2 from rbac import models
  3 from django.utils.safestring import mark_safe
  4 
  5 def permission_session(user_id,request):
  6     """
  7 
  8     :param user_id:  rbac中的user表中一條數據id
  9     :param request:
 10     :return:
 11     """
 12     # obj = models.User.objects.filter(username='楊明').first()
 13     #
 14     # # x = models.User2Role.objects.filter(user_id=obj.id)
 15     # # [User2Role,User2Role,User2Role]
 16     #
 17     # role_list = models.Role.objects.filter(users__user_id=obj.id)
 18     # # [Role,]
 19     # from django.db.models import Count
 20     # # permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url','action__code').annotate(c=Count('id'))
 21     # permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url','action__code').distinct()
 22     """
 23     [
 24         {permission_url: '/index.html', action_code:'GET'},
 25         {permission_url: '/index.html', action_code:'POST'},
 26         {permission_url: '/index.html', action_code:'DEL'},
 27         {permission_url: '/index.html', action_code:'Edit'},
 28         {permission_url: '/order.html', action_code:'GET'},
 29         {permission_url: '/order.html', action_code:'POST'},
 30         {permission_url: '/order.html', action_code:'DEL'},
 31         {permission_url: '/order.html', action_code:'Edit'},
 32     ]
 33     放在Session中
 34     /index.html?md=GET
 35 
 36     {
 37         '/index.html': [GET,POST,DEL,Edit],
 38         '/order.html': [GET,POST,DEL,Edit],
 39     }
 40 
 41     """
 42 
 43     user_permission_dict = {
 44         '/ah-index.html': ["GET","POST","DEL","Edit"],
 45         '/order.html':  ["GET","POST","DEL","Edit"],
 46         '/index-(\d+).html':  ["GET","POST","DEL","Edit"],
 47     }
 48 
 49     request.session['user_permission_dict'] = user_permission_dict
 50 
 51 
 52 def menu(user_id,current_url):
 53     """
 54     根據用戶ID,當前URL:獲取用戶所有菜單以及權限,是否顯示,是否打開
 55     :param user_id:
 56     :param current_url:
 57     :return:
 58     """
 59     # 所有菜單:處理成當前用關聯的菜單
 60     all_menu_list = models.Menu.objects.all().values('id','caption','parent_id')
 61     user = models.User.objects.filter(id=user_id).first()
 62     role_list = models.Role.objects.filter(users__user=user)
 63     permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__id','permission__url','permission__menu_id','permission__caption').distinct()
 64     ##### 將權限掛靠到菜單上 ########
 65     all_menu_dict = {}
 66     for row in all_menu_list:
 67         row['child'] = []      # 添加孩子
 68         row['status'] = False # 是否顯示菜單
 69         row['opened'] = False # 是否默認打開
 70         all_menu_dict[row['id']] = row
 71 
 72     for per in permission_list:
 73         if not per['permission__menu_id']:
 74             continue
 75 
 76         item = {
 77             'id':per['permission__id'],
 78             'caption':per['permission__caption'],
 79             'parent_id':per['permission__menu_id'],
 80             'url': per['permission__url'],
 81             'status': True,
 82             'opened': False
 83         }
 84         if re.match(per['permission__url'],current_url):
 85             item['opened'] = True
 86         pid = item['parent_id']
 87         all_menu_dict[pid]['child'].append(item)
 88 
 89         # 將當前權限前輩status=True
 90         temp = pid # 1.父親ID
 91         while not all_menu_dict[temp]['status']:
 92             all_menu_dict[temp]['status'] = True
 93             temp = all_menu_dict[temp]['parent_id']
 94             if not temp:
 95                 break
 96 
 97         # 將當前權限前輩opened=True
 98         if item['opened']:
 99             temp1 = pid # 1.父親ID
100             while not all_menu_dict[temp1]['opened']:
101                 all_menu_dict[temp1]['opened'] = True
102                 temp1 = all_menu_dict[temp1]['parent_id']
103                 if not temp1:
104                     break
105     # ############ 處理菜單和菜單之間的等級關系 ############
106 
107     result = []
108     for row in all_menu_list:
109         pid = row['parent_id']
110         if pid:
111             all_menu_dict[pid]['child'].append(row)
112         else:
113             result.append(row)
114 
115     ##################### 結構化處理結果 #####################
116 
117     # for row in result:
118     #     print(row['caption'],row['status'],row['opened'],row)
119 
120 
121     def menu_tree(menu_list):
122         tpl1 = """
123         <div class='menu-item'>
124             <div class='menu-header'>{0}</div>
125             <div class='menu-body {2}'>{1}</div>
126         </div>
127         """
128         tpl2 = """
129         <a href='{0}' class='{1}'>{2}</a>
130         """
131 
132         menu_str = ""
133         for menu in menu_list:
134             if not menu['status']:
135                 continue
136             # menu: 菜單,權限(url)
137             if menu.get('url'):
138                 # 權限
139                 menu_str += tpl2.format(menu['url'],'active' if menu['opened'] else "",menu['caption'])
140             else:
141                 # 菜單
142                 if menu['child']:
143                     child_html = menu_tree(menu['child'])
144                 else:
145                     child_html = ""
146                 menu_str += tpl1.format(menu['caption'], child_html,"" if menu['opened'] else 'hide')
147 
148         return menu_str
149     menu_html = menu_tree(result)
150     return menu_html
151 
152 
153 # simple_tag
154 def css():
155     v = """
156         <style>
157         .hide{
158             display: none;
159         }
160         .menu-body{
161             margin-left: 20px;
162         }
163         .menu-body a{
164             display: block;
165         }
166         .menu-body a.active{
167             color: red;
168         }
169     </style>
170         """
171     return v
172 
173 # simple_tag
174 def js():
175     v = """
176         <script>
177         $(function(){
178 
179             $('.menu-header').click(function(){
180                 $(this).next().removeClass('hide').parent().siblings().find('.menu-body').addClass('hide');
181 
182             })
183 
184         })
185     </script>
186     """
187     return mark_safe(v)
View Code

 

#另外創建一個app,  動態生成多級菜單,做成一個插件,后另一個APP中如果需要,直接導入:

示例:

APP01下的views.py

from django.shortcuts import render,HttpResponse,redirect
from rbac import service,server
# Create your views here.

def menu_test(request):
    css=server.css()
    js=server.js()
    result=server.menu(1,'/index')
    # print(result,'[[[[[[')
    return render(request,'menu.html',{'css':css,'js':js,'result':result})

 

代碼詳解:

from django.shortcuts import render, HttpResponse, redirect
from rbac import models
from django.utils.safestring import mark_safe
from django.db.models import Q, Count
import re

def menu(user_id, current_url):
    # 當前用戶信息
    user = models.User.objects.filter(id=user_id).first()

    # 當前用戶的所有角色
    role_list = models.Role.objects.filter(users__user=user)

    # 這里一跨表就到了Role2User 里面
    # p2a = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url',
    #                                                                                            'action__code',)
    #《 獲取當前用戶角色的權限列表》
    permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__id',
                                                                                              'permission__caption',
                                                                                              'permission__url',
                                                                                              'permission__menu',
                                                                                              'permission__menu_id',
                                                                                              'role_id').distinct()
    
  all_menu_list
= models.Menu.objects.all().values('id', 'caption', 'parent_id')
   1、獲取當前所有菜單

    all_menu_list
    <QuerySet [{'id': 1, 'caption': '博客管理', 'parent_id': None}, {'id': 2, 'caption': '用戶管理', 'parent_id': None}, {'id': 3, 'caption': '訂單管理', 'parent_id': None}, {'id': 4, 'ca  ption': '待處理', 'parent_id': 3}]>

  
  2、菜單的結果中添加child
all_menu_dict = {} for row in all_menu_list: row['child'] = [] #添加孩子 row['status'] = False # 表示是否顯示,最終在頁面上,讓該顯示的顯示 row['opend'] = False # 表示當前默認是否應該展開 all_menu_dict[row['id']] = row # print(all_menu_dict) # print(all_menu_list)

  #結果

  all_menu_dict={}
  for row in all_menu_list:
  row[‘child’]=‘’
  row[‘status’]=False
  row[‘opened’]=False
  all_menu_dict[‘id’]=row
  結果:
  {
  1: {'opend': False, 'child': [], 'caption': '博客管理', 'parent_id': None, 'status': False, 'id': 1},
  2: {'opend': False, 'child': [], 'caption': '用戶管理', 'parent_id': None, 'status': False, 'id': 2},
  3: {'opend': False, 'child': [], 'caption': '訂單管理', 'parent_id': None, 'status': False, 'id': 3},
  4: {'opend': False, 'child': [], 'caption': '待處理', 'parent_id': 3, 'status': False, 'id': 4}
  }


  3、獲取當前用戶角色的權限列表,看上面的《獲取當前用戶角色的權限列表》

  <QuerySet
  [{'permission__menu': 4, 'permission__menu_id': 4, 'permission__url': '/process', 'permission_id': 4, 'permission__caption': '處理訂單'},
  {'permission__menu': 2, 'permission__menu_id': 2, 'permission__url': '/index', 'permission_id': 1, 'permission__caption': '用戶管理'},
  {'permission__menu': 3, 'permission__menu_id': 3, 'permission__url': '/order', 'permission_id': 2, 'permission__caption': '訂單管理'}
  ]>


for per in permission_list: if not per['permission__menu_id']: continue item = { 'id': per['permission__id'],#’permission_id': 2,4 'caption': per['permission__caption'], #'permission__caption': '訂單管理’,,處理訂單,, 'parent_id': per['permission__menu_id'], #'permission__menu_id': 3, 'url': per['permission__url'], #'permission__url': '/order',/process 'status': True, 'opend': False, } if re.match(per['permission__url'],current_url): item['opend'] = True ##item={‘url': '/order', 'status': True, 'opend': True, 'id': 2, 'parent_id': 3, 'caption': '訂單管理'} pid = item['parent_id'] #'parent_id': 3——'permission__menu_id': 4 # all_menu_dict[pid]['child'].append(item)      #最后all_menu_dict的結果:
    
{

    1: {'opend': False, 'id': 1, 'status': False, 'caption': '博客管理', 'child': [], 'parent_id': None},
    2: {'opend': False, 'id': 2, 'status': False, 'caption': '用戶管理', 'child': [{'url': '/index', 'opend': False, 'id': 1, 'status': True, 'caption': '用戶管理', 'parent_id': 2}], 'parent_id': None},
    3: {'opend': False, 'id': 3, 'status': False, 'caption': '訂單管理', 'child': [{'url': '/order', 'opend': True, 'id': 2, 'status': True, 'caption': '訂單管理', 'parent_id': 3}], 'parent_id': None},
    4: {'opend': False, 'id': 4, 'status': False, 'caption': '待處理', 'child': [{'url': '/process', 'opend': False, 'id': 4, 'status': True, 'caption': '處理訂單', 'parent_id': 4}], 'parent_id': 3}

    }

# 將當前權限前輩的[status]=True temp = pid while not all_menu_dict[temp]['status']: all_menu_dict[temp]['status'] = True temp = all_menu_dict[temp]['parent_id'] if not temp: break # # 將當前權限前輩opend=True if item['opend']: temp1 = pid while not all_menu_dict[temp1]['opend']: all_menu_dict[temp1]['opend'] = True temp1 = all_menu_dict[temp1]['parent_id'] if not temp1: break # print(all_menu_dict) # 當前URL # all_menu_dict[pid]['status']=True # all_menu_dict[all_menu_dict[pid]['parent_id']]['status']=True # print(item)#{'opend': False, 'id': 3, 'parent_id': 1, 'status': True, 'url': '/blogs.html', 'caption': '博客管理'} # print(all_menu_dict)# # {1: {'opend': False, 'caption': '用戶管理', 'status': False, 'parent_id': None, 'id': 1, # 'child': [{'url': '/blogs.html', 'opend': False, 'caption': '博客管理', 'status': True, 'parent_id': 1, 'id': 3}]}, # 2: {'opend': False, 'caption': '訂單管理', 'status': False, 'parent_id': None, 'id': 2, 'child': []}, # 3: {'opend': False, 'caption': '博客管理', 'status': False, 'parent_id': 1, 'id': 3, 'child': [{'url': '/user.html', 'opend': False, 'caption': '用戶管理', 'status': True, 'parent_id': 3, 'id': 1}]}, # 4: {'opend': False, 'caption': '任務管理', 'status': False, 'parent_id': 2, 'id': 4, 'child': []}, 5: {'opend': False, 'caption': '待處理任務', 'status': False, 'parent_id': 4, 'id': 5, 'child': []} # } # ######處理菜單和菜單之間的等級關系# # print(all_menu_list) result = [] # 最終結構化數據結果 for row in all_menu_list: pid = row['parent_id'] if pid: # print(row) all_menu_dict[pid]['child'].append(row) else: result.append(row) ###結構化數據處理結束 最后結果result變成這樣:

result=

  [{'child': [], 'id': 1, 'status': False, 'parent_id': None, 'caption': '博客管理', 'opend': False},
  {'child': [{'id': 1, 'url': '/index', 'status': True, 'parent_id': 2, 'caption': '用戶管理', 'opend': False}], 'id': 2, 'status': True, 'parent_id': None, 'caption': '用戶管理', 'opend': False},
  {'child': [{'id': 2, 'url': '/order', 'status': True, 'parent_id': 3, 'caption': '訂單管理', 'opend': True},{'child': [{'id': 4, 'url': '/process', 'status': True, 'parent_id': 4, 'caption': '處理訂單','opend':False}],
'id': 4, 'status': True, 'parent_id': 3, 'caption': '待處理', 'opend': False}], 'id': 3, 'status': True, 'parent_id': None, 'caption': '訂單管理', 'opend': True}]

  #前端生成HTML標簽:
def menu_tree(menu_list): tpl1 = """ <div class='menu-item'> <div class='menu-header'>{0}</div> <div class='menu-body {2}'>{1}</div> </div> """ tpl2 = """ <a href='{0}' class='{1}'>{2}</a> """ menu_str = "" for menu in menu_list: # for menu in menu_list: if not menu['status']: continue # if not menu['status']: # continue if menu.get('url'): # 權限 menu_str += tpl2.format(menu['url'], 'active' if menu['opend'] else "", menu['caption']) else: # 菜單 # 如果是菜單就還有child if menu['child']: child_html = menu_tree(menu['child']) else: child_html = "" menu_str += tpl1.format(menu['caption'], child_html, "" if menu['opend'] else 'hide') return menu_str menu_html = menu_tree(result) return menu_html # ####生成菜單 # return render(request,'menus.html') def css(): v = """ <style> .hide{ display: none; } .menu-body{ margin-left: 20px; } .menu-body a{ display: block; } .menu-body a.active{ color: red; } </style> """ return v # simple_tag def js(): v = """ <script> $(function(){ $('.menu-header').click(function(){ $(this).next().removeClass('hide').parent().siblings().find('.menu-body').addClass('hide'); }) }) </script> """ return mark_safe(v)

最后效果: 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM