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