• 权限(二)


     一. 把自己写的对权限的处理变成一个可以随时调用的组件(步骤)

    1.在项目中创建一个app

    命令:startapp rbac

    2.在rbac app下创建一个文件夹,service,将对权限处理的内容放到该文件夹下

    (1) 为该组件做数据库准备

    models.py:

     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:

    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.py

     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中也要相应修改路径

    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 }}

  • 相关阅读:
    【转】滑动窗口与拥塞控制
    LeetCode 34 :Find First and Last Position of Element in Sorted Array
    主要电商模式介绍
    使用springboot创建邮件服务器
    解决Windows下端口占用问题
    [leetcode]给定二维平面上的n个点,找出位于同一直线上的点的最大数目
    获得超类的泛型参数在子类实例化传入的实际类型
    构造单例的五种方法
    20162308 2017-2018-2 《程序设计与数据结构》第11周学习总结
    20162308 2017-2018-2 《程序设计与数据结构》第十周学习总结
  • 原文地址:https://www.cnblogs.com/shanghongyun/p/9941438.html
Copyright © 2020-2023  润新知