1.在項目中建立一個apphtml
命令:startapp rbacpython
2.在rbac app下建立一個文件夾,service,將對權限處理的內容放到該文件夾下web
(1) 爲該組件作數據庫準備數據庫
在models.py中:django
1 from django.db import models 2 3 class User(models.Model): 4 name=models.CharField(max_length=32) 5 pwd=models.CharField(max_length=32) 6 roles=models.ManyToManyField(to="Role") 7 def __str__(self): 8 return self.name 9 10 class Role(models.Model): 11 title=models.CharField(max_length=32) 12 permissions=models.ManyToManyField(to="Permission") 13 def __str__(self): 14 return self.title 15 16 class Permission(models.Model): 17 title=models.CharField(max_length=32) 18 url=models.CharField(max_length=32) 19 def __str__(self): 20 return self.title
(2)爲便於利用admin組件瀏覽器
在admin.py中:session
1 from django.contrib import admin 2 from rbac.models import * 3 admin.site.register(User) 4 admin.site.register(Role) 5 class PermissionConfig(admin.ModelAdmin): 6 list_display=["pk","title","url"] 7 ordering = ["-pk"] 8 admin.site.register(Permission,PermissionConfig)
(3)在service文件夾下建立middleware.pyapp
1 import re 2 from django.utils.deprecation import MiddlewareMixin 3 from django.shortcuts import HttpResponse,redirect 4 class SessionMiddleware(MiddlewareMixin): 5 def process_request(self, request): 6 path=request.path 7 permission=request.session.get("permission") 8 # 白名單 9 for reg in ["/login/","/admin/*"]: 10 ret=re.search(reg,path) 11 if ret: 12 return None 13 # 判斷是否登陸 14 user_id=request.session.get("user_id") 15 if not user_id: 16 return redirect("/login/") 17 # 校驗權限 18 for reg in permission: 19 reg="^%s$" % reg 20 ret=re.search(reg,path) 21 if ret: 22 return None 23 return HttpResponse("無權訪問")
(4)在service文件夾下建立rbac.py函數
1 from rbac.models import * 2 def initial_sesson(request,user): 3 permissions__url=Role.objects.filter(user__name=user).values("permissions__url") 4 print(permissions__url) 5 permissions__url_list=[] 6 for item in permissions__url: 7 print(item["permissions__url"]) 8 permissions__url_list.append(item["permissions__url"]) 9 print(type(permissions__url_list),permissions__url_list) 10 request.session["permission"]=permissions__url_list
3.Settings中也要相應修改路徑url
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'rbac.service.middleware.SessionMiddleware', ]
同時值得注意的是,settings中的INSTALLED_APPS,也要添加rbac
1 INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 'app01.apps.App01Config', 9 'rbac', 10 'web', 11 ]
3.之後處理權限問題時,只須要調用inital_session便可
1 from django.shortcuts import render,HttpResponse 2 from rbac.models import * 3 from rbac.service.rbac import initial_sesson #引入 4 def login(request): 5 if request.method=="GET": 6 return render(request,"web/login.html") 7 else: 8 user=request.POST.get("user") 9 pwd=request.POST.get("pwd") 10 use=User.objects.filter(name=user,pwd=pwd).first() 11 if use: 12 request.session["user_id"]=use.pk 13 initial_sesson(request,user) #調用 14 return HttpResponse("登陸成功") 15 else: 16 return HttpResponse("用戶名或密碼錯誤")
1.問題關鍵:
(1)因爲角色的不一樣,所擁有的權限不一樣,左側菜單列不一樣
(2)在全部的權限中,並非全都要顯示在左側菜單列,要根據狀況有必定的篩選
本次目的:增刪該查,只有查做爲左側菜單顯示
2.解決方案:
(1) 在permission表中新添加兩個字段is_menu icon
1 class Permission(models.Model): 2 title=models.CharField(max_length=32) 3 url=models.CharField(max_length=32) 4 is_menu=models.BooleanField(default=False) 5 icon=models.CharField(max_length=64,default="",blank=True,null=True) 6 def __str__(self): 7 return self.title
(2)在admin.py中配置讓這兩個字段顯示
1 class PermissionConfig(admin.ModelAdmin): 2 list_display=["pk","title","url","is_menu","icon"] 3 list_editable = ["url","icon"] #注意問題:list_editable中的元素必須是list_display=中的元素 4 search_fields = ["title"] 5 admin.site.register(Permission,PermissionConfig)
(3)在rbac.py中:
當is_nemu爲true時,title,icon,url三項都注入到session中;當is_nemu爲false時,只有url注入到session中
1 from rbac.models import Role 2 def initial_sesson(request,user): 3 """ 4 功能:將當前登陸人的全部權限錄入session中 5 :param user: 當前登陸人 6 """ 7 # 查詢當前登陸人的全部權限列表 8 # 查看當前登陸人的全部角色 9 # ret=Role.objects.filter(user=user) 10 permissions = Role.objects.filter(user__name=user).values("permissions__url", 11 "permissions__is_menu", 12 "permissions__title", 13 "permissions__icon", 14 ).distinct() 15 permission_list = [] 16 permission_menu_list = [] 17 for item in permissions: 18 # 構建權限列表 19 permission_list.append(item["permissions__url"]) 20 21 # 構建菜單權限列表 22 if item["permissions__is_menu"]: 23 permission_menu_list.append({ 24 "title":item["permissions__title"], 25 "icon":item["permissions__icon"], 26 "url":item["permissions__url"], 27 }) 28 29 # 將當前登陸人的權限列表注入session中 30 request.session["permission_list"] = permission_list 31 # 將當前登陸人的菜單權限列表注入session中 32 print("permission_menu_list",permission_menu_list) 33 request.session["permission_menu_list"] = permission_menu_list
(4)在母板中,循環request.session構建左側菜單a標籤
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>掌上大學</title> 6 </head> 7 <body> 8 <div> 9 {% for foo in request.session.permission_menu_list %} 10 <a href="{{ foo.url }}">{{ foo.title }}</a> 11 {% endfor %} 12 13 {% block content %} 14 {% endblock %} 15 </div> 16 </body> 17 </html>
缺點:要在每個菜單視圖函數中添加這樣一段代碼
爲每一個左側菜單動態添加active類 ,改進方式準備知識
1.自定義過濾器
自定義過濾器的步驟:
(1)檢查settings中的install_app是否包含該app
(2)在APP下加一個包:必須叫templatetags
(3)建一個python腳本:名字隨意
(4)在該腳本中:
1 from django.template import Library 2 register=Library() #前兩句是固定的 3 4 @register.filter #讓一個函數變成過濾器的語法 5 def mul(x): 6 return x*2
(5)在HTML中的應用語法:
1 {% load glq %} #遇到load,Django會固定循環每個app下的templatetags語法 2 {{ 2|mul }} #若是有其餘參數,放在函數名後,用空格隔開
寫完要重啓項目,過濾器才能用
2.能夠渲染標籤的過濾器
(1)過濾器的編寫
1 from django.template import Library 2 register=Library() 3 from django.utils.safestring import mark_safe # 4 5 @register.filter 6 def tag(val): 7 return mark_safe("<a href='www.baidu.com'>%s</a>" % val)
(2) HTML中的應用:
{% load glq %}
{{ '點擊跳轉'|tag }}
自定義過濾器的侷限性:參數最多隻能有兩個
3.自定義標籤
語法:與自定義過濾器語法大致相同
不一樣之處:
(1)@register.simple_tag #讓一個函數變成自定義標籤的語法
def mul_tag(x,y,z):
return x*y*z
(2)在HTML中:
1 {% load glq %} 2 {% mul_tag 2 3 5 %} 前者用{{ }}調用,歐後者用{% %}調用
4.includsion_tags:將母版和自定義標籤結合
(1)定義includsion_tags:
1 @register.inclusion_tag("web/menu.html") 2 def get_menu_style(request): 3 menu_list=[11,22,33] 4 return {"menu_list":menu_list} #返回值儘可能用字典,要否則會報錯
(2)編寫用到的menu.html:
1 <ul> 2 {% for foo in menu_list %} 3 <li>{{ foo }}</li> 4 {% endfor %} 5 </ul>
(3)在HTML中的調用:
{% load glq %}
{% get_menu_style request %}
優勢:數據之須要傳一次
因此:!!!!!!!!!
對於動態添加active需求的處理
讓母版調用get_menu_styles方法:
1 @register.inclusion_tag("web/menu.html") 2 def get_menu_styles(request): 3 permission_menu_list = request.session.get("permission_menu_list") 4 for item in permission_menu_list: 5 if re.search("^{}$".format(item["url"]), request.path): 6 item["class"] = "active" 7 return {"permission_menu_list":permission_menu_list}
menu.html:
1 <ul> 2 {% for foo in menu_list %} 3 <li>{{ foo }}</li> 4 {% endfor %} 5 </ul>
五.在瀏覽器訪問一個頁面的過程當中render到底作了什麼
六.母版繼承補充:
母版繼承除了能夠在在所繼承的母版中添加某一部份內容外,還能夠在一個完整的HTML中的某一部分使用另外一個HTML
語法:{% include "web/other.html" %}
七.補充細節問題:
Ajax想發送一個這樣的name
必定要加」 」
若是把js抽出來,能夠在HTML頁面中添加一個沒有用的標籤,<div class={{ name }}></div>用來存儲{{ class }}