1 table structure design
1 from django.db import models 2 3 # Create your models here. 4 from django.db import models 5 6 # Create your models here. 7 8 9 # User table 10 class UserInfo(models.Model): 11 username = models.CharField(max_length=16, verbose_name="username") 12 password = models.CharField(max_length=32, verbose_name="password") 13 roles = models.ManyToManyField(to="Role", null=True, blank=True) 14 # null=TRUE tells the database that this field can be empty, blank=True tells djangoadmin that it can be left blank 15 16 #Show specific content 17 def __str__(self): 18 return self.username 19 20 # Let the field display Chinese 21 class Meta: 22 verbose_name = "User table" 23 verbose_name_plural = verbose_name twenty four 25 26 # role 27 class Role(models.Model): 28 title = models.CharField(max_length=32, verbose_name="Character name") 29 permissions = models.ManyToManyField(to="Permission") 30 31 def __str__(self): 32 return self.title 33 34 class Meta: 35 verbose_name = "Character List" 36 verbose_name_plural = verbose_name 37 38 39 # Permission table 40 class Permission(models.Model): 41 title = models.CharField(max_length=16, verbose_name="Permission name") 42 url = models.CharField(max_length=255, verbose_name="URL") 43 is_menu = models.BooleanField(default=False, verbose_name="Can be displayed as a menu") 44 icon = models.CharField(max_length=16, verbose_name="menu icon", null=True, blank=True) 45 46 def __str__(self): 47 return self.title 48 49 class Meta: 50 verbose_name = "Permission Table" 51 verbose_name_plural = verbose_name
View Code
2. Create rbac permission management project
1. In order to achieve decoupling of the project structure, write the permission system as a separate app
1. Create APP
Steps to create an app in Django
1. Run python manage.py startapp rbac in the terminal
2. Register app in settings.py
rbac.apps.RbacConfig
2. Execute two commands to synchronize the table structure to the database and write the statement to create the database in the models file of rbac.
1. python manage.py makemigrations
2. python manage.py migrate
3. Enter data
With Django Admin
Usage of Django admin
1. Create a super user to log in to the admin management background
python manage.py createsuperuser
2. Register the table we wrote in Django admin
Register the model in app/admin.py according to a fixed format
as follows:
1 from django.contrib import admin 2 from rbac import models 3 # Registered user table 4 admin.site.register(models.UserInfo) 5 #Registered role table 6 admin.site.register(models.Role) 7 8 9 # Customize a permission management class 10 class PermissionAdmin(admin.ModelAdmin): 11 # Tell django admin to display the fields of my table on the page 12 list_display = ["title","url","is_menu","icon"] 13 # You can edit the url on the list page 14 list_editable = ["url","icon","is_menu"] 15 16 17 admin.site.register(models.Permission,PermissionAdmin)
3. Permission query
It is best to encapsulate the permission query code into a separate function, so that you can directly use the rbac permission management you wrote in the future.
1 Create a new python package under the rbac directory. The name can be whatever you want, and then create a new py file. The name can be whatever you want. Here it is: permission.py
1 from django.conf import settings 2 3 4 def init_permission(request, user_obj): 5'' 6 Function to initialize permission information and menu information in session 7 :param request: request object 8:param user_obj: current logged in user 9 :return: 10'' 11 12 # user_obj.roles.all() to access all roles of the current user 13 ret = user_obj.roles.all().values("permissions__url", 14 "permissions__icon", 15 "permissions__is_menu", 16 "permissions__title" 17).distinct() # Obtain the permissions after deduplication 18 #Define a permission list 19 permission_list = [] 20 #Define a list specifically used to store the current user menu 21 menu_list = [] 22 for item in ret: 23 print(item) # item is a large list 24 permission_list.append({"permissions__url": item["permissions__url"]}) # Add to permission list 25 if item["permissions__is_menu"]: # if true 26 menu_list.append({ 27 "title": item["permissions__title"], 28 "icon": item["permissions__icon"], 29 "url": item["permissions__url"] 30}) 31 32 # Save the user permission list information into the session 33 request.session[settings.PERMISSION_SESSION_KEY] = permission_list 34 # Store all menus of the current user in sessioin 35 request.session[settings.MENU_SESSION_KEY] = menu_list
View Code
2 setting.py file configuration
# Set whitelist PERMISSION_WHITE_URL=[ "/login/", "/admin/.*", ] #Permission list PERMISSION_SESSION_KEY="permission_list" #menu list MENU_SESSION_KEY="menu_list"
Four permission verification
The permission verification function should be placed in the process_request() method in the middleware
1 Create a new python package middleware under the rbac directory, and then create an rbac.py file. The name can be whatever you want.
1 ''' 2 Custom rbac middleware 3'' 4 from django.utils.deprecation import MiddlewareMixin 5 from django.shortcuts import redirect,HttpResponse,render 6 import re 7 from django.conf import settings 8 9 class RBACMiddleware(MiddlewareMixin): 10 def process_request(self,request): 11 ''' 12 Custom permission verification middleware 13 :param request: request object 14 :return: 15'' 16 # 1 Get the URL accessed by the current request 17 url=request.path_info # request.get_full_path() 18 # Filter whitelist 19 for item in settings.PERMISSION_WHITE_URL: 20 reg="^{}$".format(item) 21 if re.match(reg,url): 22 return None 23 # Get the permission list of the current user 24 permission_list=request.session.get(settings.PERMISSION_SESSION_KEY,None) 25 # Perform permission verification 26 if permission_list is None: 27 # The user is not logged in 28 return redirect("/login/") 29 for i in permission_list: 30 reg="^{}$".format(i['permissions__url']) 31 if re.match(reg,url): 32 break 33 else: 34 return HttpResponse("You do not have this permission")
View Code
2 Then register it in the setting.py file
'rbac.middleware.rbac.RBACMiddleware',
5. The reference to the project login function is to import the function that just encapsulated initialization permissions.
''' Views related to the user are written here ''' from django.shortcuts import redirect, render, HttpResponse from rbac.models import UserInfo from rbac.service.permission import init_permission def login(request): error_msg = "" if request.method == "POST": # Get username and password username = request.POST.get("username") pwd = request.POST.get("password") # verify user_obj = UserInfo.objects.filter(username=username, password=pwd).first() if user_obj: # login successful # Call the encapsulated initialization function which contains the permission list and display menu init_permission(request,user_obj) return redirect("/customer/list/") else: error_msg = "Wrong username or password" return render(request, "login.html")
6. Template language referenced in pages
1 First create a new python package under rbac with the name templatetags (the name must be this) and then create a new py file with any name. I call it ooxx here.
filename is to call the page you returned the result, show_menu is the name of your customized template language
from django import template from luffy_permission import settings register = template.Library() @register.inclusion_tag(filename="my_menu.html") def show_menu(request): #menu_list is the user's menu list you get from the session menu_list = request.session[settings.MENU_SESSION_KEY] return {"menu_list": menu_list} # Return menu_list to the page my_menu.html
2 Create a new file my_menu.html with the same name as the filename. Create a new templates in the rbac directory.
The menu_list in this is the return result you customized above. menu.icon represents the icon field, and menu.title represents the menu name.
1 {% for menu in menu_list %} 2 <a href="{<!-- -->{ menu.url }}" class="active"> 3 <span class="icon-wrap"><i class="fa {<!-- -->{ menu.icon }}"></i></span> {<!-- -->{ menu.title }}</a> 4 5 {% endfor %}
3. To allow you to reference ooxx in the HTML page that you actually show to the user, add this to the div of the menu. request is a parameter of show_menu.
<div class="static-menu"> {% load ooxx %} {% show_menu request %} </div>
Seven rbac permission directory structure
How to reference rbac permission management in a new project######################################## #################
1. Copy the rbac app to the project
2. Delete all migration records in the rbac/migrations directory.
3. Register the rbac app in the project
4. Create database migration (execute those two commands)
1. python manage.py makemigrations 2. python manage.py migrate
5. Register admin and enter data –> automatically discover and enter the permission URL
6. Initialize permission information during the login process, and configure the login function to reference the encapsulated initial permissions.
from django.shortcuts import render, HttpResponse, redirect from django.conf import settings from rbac.service.permission import init_permission from rbac.models import UserInfo # Create your views here. def login(request): if request.method == "POST": username = request.POST.get("username") pwd = request.POST.get("password") user_obj = UserInfo.objects.filter(username=username, password=pwd).first() if user_obj: # login successful #Initialize permission information init_permission(request, user_obj) return redirect("/book_list/") return render(request, "login.html") def book_list(request): return render(request, "book_list.html") def book_add(request): return render(request, "book_add.html")
View Code
7. Register middleware
8. Set permission-related configuration items in settings.py
# Set whitelist PERMISSION_WHITE_URL=[ "/login/", "/admin/.*", ] #Permission list PERMISSION_SESSION_KEY="permission_list" #menu list MENU_SESSION_KEY="menu_list"
9 Reference in html list page
{% load ooxx %} {% show_menu request %}