Role (title, permission) -(ManyToManyField)- User (name, pwd, roles) html
| 正則表達式
(ManyToManyField)django
| session
Permission (title, url)app
Django_rbac/ rbca/models.pyide
from django.db import models # Create your models here. 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
Django_rbac/ rbac/service/permission.py post
用於獲取當前用戶的權限信息測試
""" 爲了解耦,將處理權限的代碼保存在組件裏面 """ def initial_session(user,request): # 查看當前用戶的全部的權限 # 由於會有values 的原理會致使有重複須要去重 ret = user.roles.all().values("permissions__url").distinct() permission_list = [] # 將全部的權限保存在一個列表裏面,稍微處理下數據便於操做 for i in ret: permission_list.append(i["permissions__url"]) # 把用戶的用戶權限保存在 session 裏面 request.session["permission_list"] = permission_list
Django_rbac/rbac/service/rbca.py url
基於當前用戶的權限信息對來訪請求進行邏輯判斷篩選返回結果spa
爲了避免冗餘代碼寫在中間件中,對每一次的請求都作計算
因中間件的工做機制致使全部的請求都被計算,須要對特殊的 URL 進行特殊處理
import re from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, redirect """ 寫在中間件裏面能夠徹底避免每次都要重複校驗的問題 在請求來的時候進行校驗,所以要寫在 process_request 方法裏面 """ class ValidPermission(MiddlewareMixin): def process_request(self,request): # 當前訪問路徑 current_path = request.path_info """ 檢查是否屬於白名單 admin 的內部流程 不容許一上來就訪問首頁,必需要跳轉到 登錄頁面 http://127.0.0.1:8000/admin/login/?next=/admin/ 第二次跳轉到登陸頁面的請求若是沒有被定義可經過就會被攔截 沒法只使用 admin 爲過濾選項 不能用 in 單純的判斷,仍是要用到正則處理 須要放過全部 admin 開頭的 url """ valid_url_list = ["/login/","/reg/","/admin/.*"] for valid_url in valid_url_list: ret = re.match(valid_url,current_path) if ret: # 中間件 return None 表示這個中間件已經執行完畢 return None """ 校驗是否登陸 對於沒有登錄的用戶返回報錯應該是讓他去登錄 """ user_id = request.session.get("user_id") if not user_id: return redirect("/login/") """ 校驗權限 在編輯,以及刪除頁面的時候 url 不是固定的, 會有內含的參數,所以權限列表裏面不能僅僅是寫死的url 也不能再單純的用 in 來判斷。仍是要靠正則來處理 將權限列表裏面的權限信息用 正則表達式來保存 而後對訪問頁面進行驗證是否能夠經過來處理 """ permission_list = request.session.get("permission_list",[]) flag = False for permission in permission_list: permission = f"^{permission}$" ret = re.match(permission, current_path) if ret: flag = True break if not flag: return HttpResponse("沒有訪問權限! ") return None
不要忘記註冊在 Django_rbac\Django_rbac\settings.py 裏面
Django_rbac/app01/views.py
from django.shortcuts import render,HttpResponse import re # Create your views here. from rbac.models import * from rbac.service.perssions import initial_session def users(request): user_list=User.objects.all() return render(request,"users.html",locals()) def add_user(request): permission_list = request.session["permission_list"] return HttpResponse("add user.....") def roles(request): role_list=Role.objects.all() return render(request,"roles.html",locals()) def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") # 拿到當前用戶對象 user = User.objects.filter(name=user, pwd=pwd).first() if user: # 把用戶的id 保存在 session 裏面 request.session["user_id"] = user.pk # 查詢當前用戶的全部的權限 initial_session(user,request) return HttpResponse("登陸成功!") return render(request, "login.html",locals())
這個就比較隨意了,看個結果而已。
Django_rbac\templates\login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h4>登陸頁面</h4> <form action="" method="post"> {% csrf_token %} 用戶名:<input type="text" name="user"> 密碼:<input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
Django_rbac\templates\roles.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h4>角色列表</h4> <ul> {% for role in role_list %} <p>{{ role }}</p> {% endfor %} </ul> </body> </html>
Django_rbac\templates\users.html
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 </head> 8 <body> 9 10 <h4>用戶列表</h4> 11 <ul> 12 {% for user in user_list %} 13 <p>{{ user }}</p> 14 {% endfor %} 15 16 </ul> 17 18 </body> 19 </html>