權限(二)

 一. 把本身寫的對權限的處理變成一個能夠隨時調用的組件(步驟)

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_nemutrue,title,icon,url三項都注入到session;is_nemufalse,只有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類 

缺點:要在每個菜單視圖函數中添加這樣一段代碼

.(自定義過濾器(look)和標籤)

爲每一個左側菜單動態添加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 }}

相關文章
相關標籤/搜索