Django之RBAC基于角色的访问控制、xadmin的使用、django缓存及django信号

文章目录

      • 1、RBAC基于角色的访问控制
        • 1.1、定义
        • 1.2、应用
        • 1.3、前后台权限控制
        • 1.4、rbac的表设计
        • 1.5、models.py
        • 1.6、admin.py
      • 2、xadmin的使用
        • 2.1、安装
        • 2.2、配置
        • 2.3、使用
          • 2.3.1、站点的全局配置
          • 2.3.2、站点Model管理
        • 2.4、示例
      • 3、django缓存
        • 3.1、定义
        • 3.2、Django中提供了6种缓存方式
        • 3.3、缓存配置
        • 3.4、缓存粒度(三种粒度)
          • 3.4.1、单页面缓存
          • 3.4.2、页面中某个位置缓存(局部缓存)
          • 3.4.3、整站缓存(两个中间件)
          • 3.4.4、前后端分离后缓存使用
      • 4、django信号
        • 4.1、定义
        • 4.2、Django内置信号
        • 4.3、内置信号的使用
          • 4.3.1、方式一
          • 4.3.2、方式二
          • 4.3.3、内置信号总结

1、RBAC基于角色的访问控制

1.1、定义
RBAC是基于角色的访问控制(Role-Based Access Control)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
1.2、应用
RBAC: Role Based Access Control
Django的 Auth组件采用的认证规则就是RBAC

(1) 像专门做人员权限管理的系统(CRM系统)都是公司内部使用,所以数据量都在10w一下,一般效率要求也不是很高
(2) 用户量极大的常规项目,会分两种用户: 前台用户(三大认证) 和 后台用户(BRAC来管理)
结论: 没有特殊要求的Django项目可以直接采用Auth组件的权限六表,不需要自定义六个表,也不需要断开表关系,单可能需要自定义User表
1.3、前后台权限控制
(1) 后台用户对各表操作,是后台项目完成的,我们可以直接借助admin后台项目(Django自带的)
(2) 后期也可以用xadmin框架来做后台用户权限管理
(3) 前台用户的权限管理如何处理
	定义了一堆数据接口的视图类,不同的登录用户是否能访问这些视图类,能就代表有权限,不能就代表无权限
	前台用户权限用drf框架的三大认证
1.4、rbac的表设计
# rbac的表设计
# 最初3张表
用户表  角色表   权限表

# 5张表
用户表  角色表   权限表
用户表和角色表是多对多,需要建立第三张表
角色和权限是多对多,需要建立第三张表

# 6张表
用户表  角色表   权限表
用户表和角色表是多对多,需要建立第三张表
角色和权限是多对多,需要建立第三张表
用户和权限多对多,建立第三张表

# django内置了rbac的6张表
auth_user: 用户表,扩写
auth_group: 角色表(组表)
auth_permission: 权限表
auth_user_groups: 用户对角色的中间表
auth_group_permissions: 角色对权限的中间表
auth_user_user_permissions: 用户对权限的中间表

Django之RBAC基于角色的访问控制、xadmin的使用、django缓存及django信号_第1张图片
Django之RBAC基于角色的访问控制、xadmin的使用、django缓存及django信号_第2张图片

1.5、models.py
from django.db import models

from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    mobile = models.CharField(max_length=11, unique=True)

    def __str__(self):
        return self.username

class Book(models.Model):
    name = models.CharField(max_length=64)

    def __str__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=64)

    def __str__(self):
        return self.name
1.6、admin.py
from . import models

from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin

# 自定义User表后,admin界面管理User类
class UserAdmin(DjangoUserAdmin):
    # 添加用户课操作字段
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2', 'is_staff', 'mobile', 'groups', 'user_permissions'),
        }),
    )
    # 展示用户呈现的字段
    list_display = ('username', 'mobile', 'is_staff', 'is_active', 'is_superuser')


admin.site.register(models.User, UserAdmin)
admin.site.register(models.Book)
admin.site.register(models.Car)

这样就可以登陆到admin后台进行操作了

2、xadmin的使用

xadmin是Django的第三方扩展,可以使Django的admin站点使用更方便,django内置了一个admin,有的人觉得丑,功能不够强大,这群人写了一个叫xadmin的,用来替换admin

文档:https://xadmin.readthedocs.io/en/latest/index.html

2.1、安装
django 1.x版本安装: pip install xadmin
django 2.x版本安装: pip install git+git://github.com/sshwsfc/xadmin.git@django2
               	   pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2
2.2、配置
INSTALLED_APPS = [
    ...
    'xadmin',
    'crispy_forms',
    'reversion',
    ...
]

# 修改使用中文界面
LANGUAGE_CODE = 'zh-hans'

# 修改时区
TIME_ZONE = 'Asia/Shanghai'

# 数据迁移
python manage.py makemigrations
python manage.py migrate

# 在总路由中添加xadmin的路由信息
import xadmin
xadmin.autodiscover()

# version模块自动注册需要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models()

urlpatterns = [
    path(r'xadmin/', xadmin.site.urls)
]

# 创建超级用户
python manage.py createsuperuser

# 登录,访问地址,输入用户名密码进入
http://127.0.0.1:8000/xadmin/
2.3、使用
  • xadmin不再使用Django的admin.py,而是需要编写代码在adminx.py文件中
  • xadmin的站点管理类不用继承admin.ModelAdmin,而是直接继承object即可

例如:在子应用中创建adminx.py文件

2.3.1、站点的全局配置
import xadmin
from xadmin import views

class BaseSetting(object):
    """xadmin的基本配置"""
    enable_themes = True  # 开启主题切换功能
    use_bootswatch = True

xadmin.site.register(views.BaseAdminView, BaseSetting)

class GlobalSettings(object):
    """xadmin的全局配置"""
    site_title = xxx"  # 设置站点标题
    site_footer = "xxx有限公司"  # 设置站点的页脚
    menu_style = "accordion"  # 设置菜单折叠

xadmin.site.register(views.CommAdminView, GlobalSettings)
2.3.2、站点Model管理

xadmin可以使用的页面样式控制基本与Django原生的admin一致

  • list_display 控制列表展示的字段
list_display = ['id', 'btitle', 'bread', 'bcomment']
  • search_fields 控制可以通过搜索框搜索的字段名称,xadmin使用的是模糊查询
search_fields = ['id','btitle']
  • list_filter 可以进行过滤操作的列,对于分类、性别、状态
list_filter = ['is_delete']
  • ordering 默认排序的字段
  • readonly_fields 在编辑页面的只读字段
  • exclude 在编辑页面隐藏的字段
  • list_editable 在列表页可以快速直接编辑的字段
  • show_detail_fields 在列表页提供快速显示详情信息
  • refresh_times 指定列表页的定时刷新
refresh_times = [5, 10,30,60]  # 设置允许后端管理人员按多长时间(秒)刷新页面
  • list_export 控制列表页导出数据的可选格式
list_export = ('xls', 'xml', 'json')   list_export设置为None来禁用数据导出功能
list_export_fields = ('id', 'btitle', 'bpub_date')
  • show_bookmarks 控制是否显示书签功能
show_bookmarks = True
  • data_charts 控制显示图表的样式
data_charts = {
        "order_amount": {
          'title': '图书发布日期表', 
          "x-field": "bpub_date", 
          "y-field": ('btitle',),
          "order": ('id',)
        },
    #    支持生成多个不同的图表
    #    "order_amount": {
    #      'title': '图书发布日期表', 
    #      "x-field": "bpub_date", 
    #      "y-field": ('btitle',),
    #      "order": ('id',)
    #    },
    }

title 控制图标名称
x-field 控制x轴字段
y-field 控制y轴字段,可以是多个值
order 控制默认排序
  • model_icon 控制菜单的图标
class BookInfoAdmin(object):
    model_icon = 'fa fa-gift'

xadmin.site.register(models.BookInfo, BookInfodmin)
2.4、示例
class BookClass():
    # 该表展示的字段
    list_display = ['id', 'name', 'price','publish']
    # 按照这些字段搜索
    search_fields = ['id','name']
    # 按哪些字段过滤
    list_filter = ['is_delete']

    # 可以把数据导出成excel,json,xml格式
    list_export = ('xls', 'xml', 'json')
    # list_export设置为None来禁用数据导出功能
    list_export_fields = ('id', 'name', 'price')
    data_charts = {
        "order_amount": {
            'title': '随便写',
            "x-field": "price",
            "y-field": ('publish',),
            "order": ('id',)
        },

    }
    
# 注册
xadmin.site.register(models.Book,BookClass)

3、django缓存

3.1、定义
简单概括就是将对数据库操作查询所得到的数据放入另外一台机器上(缓存)中,当用户再次请求时,直接去缓存中拿,避免对数据库的频繁操作,加快数据的显示时间,需要知道的是,缓存里面的数据一般都设置有超时时间,缓存一般用在数据变化不大,实时率不高的情况下

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内(默认配置)再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回
3.2、Django中提供了6种缓存方式
  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)
3.3、缓存配置
通过配置,设置缓存位置
以文件缓存为例:
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',  # 指定缓存使用的引擎
        'LOCATION': 'D:\cache',  # 指定缓存的路径
        'TIMEOUT': 300,  # 缓存超时时间(默认为300秒,None表示永不过期)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存记录的数量(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }
    }
}
3.4、缓存粒度(三种粒度)
3.4.1、单页面缓存
from django.views.decorators.cache import cache_page
@cache_page(5)
def index(request):
    import time
    ctime=time.time()
    return render(request,'index.html',context={'ctime':ctime})
3.4.2、页面中某个位置缓存(局部缓存)
# 在模板页面配置
# 缓存3s,xxx唯一key,唯一的
{% load cache %}
{% cache 3 'xxx'%}
这一部分用缓存
时间为: {{ ctime }}
{% endcache %}
3.4.3、整站缓存(两个中间件)
# 在setting中配置
'django.middleware.cache.UpdateCacheMiddleware',  #第一,重写了process_response
'...',
'django.middleware.cache.FetchFromCacheMiddleware',  #最后,重写了process_requset

# 缓存过期时间
CACHE_MIDDLEWARE_SECONDS=5
3.4.4、前后端分离后缓存使用
比如查出一堆json格式数据,链表查数据库查询了8张表 
前后端分离以后: 只需要会如何把字典,字符串,对象放到缓存中

from django.core.cache import cache
class BookView(APIView):
    def get(self, request):
        res_data = cache.get('book_list_dic')  # 根据key获取
        if res_data:  # 有缓存,直接返回
            print('走了缓存')
            return Response(res_data)
        else:  # 没有缓存,再走数据库
            book_list = models.Book.objects.all()
            ser = serializer.BookSer(book_list, many=True)
            # 想把ser.data缓存起来
            cache.set('book_list_dic', ser.data,100)  # 通过key存储
            print('没走缓存')
            return Response(ser.data)

cache可以缓存所有数据类型,包括自定义的类(底层使用到了pickle)

4、django信号

4.1、定义
Django提供一种信号机制。其实就是观察者模式,又叫发布-订阅(Publish/Subscribe) 。当发生一些动作的时候,发出信号,然后监听了这个信号的函数就会执行
通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。用于在框架执行操作时解耦

应用场景:
1、记录日志(对象创建就写入日志)
2、解耦合
4.2、Django内置信号
Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发
Django 提供了一系列的内建信号,允许用户的代码获得DJango的特定操作的通知。这包含一些有用的通知:
django.db.models.signals.pre_save & django.db.models.signals.post_save

在模型 save()方法调用之前或之后发送。
django.db.models.signals.pre_delete & django.db.models.signals.post_delete

在模型delete()方法或查询集的delete() 方法调用之前或之后发送。
django.db.models.signals.m2m_changed

模型上的 ManyToManyField 修改时发送。
django.core.signals.request_started & django.core.signals.request_finished

Django建立或关闭HTTP 请求时发送。
4.3、内置信号的使用

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

4.3.1、方式一
from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception
from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate
from django.test.signals import setting_changed
from django.test.signals import template_rendered
from django.db.backends.signals import connection_created
# 放到__init__里
from django.db.models.signals import pre_save
import logging
def callBack(sender, **kwargs):
    print(sender)
    print(kwargs)
    # 创建对象写日志
    logging.basicConfig(level=logging.DEBUG)
    # logging.error('%s创建了一个%s对象'%(sender._meta.db_table,kwargs.get('instance').title))
    logging.debug('%s创建了一个%s对象'%(sender._meta.model_name,kwargs.get('instance').title))

pre_save.connect(callBack)
4.3.2、方式二
from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save)
def my_callback(sender, **kwargs):
    print("对象创建成功")
    print(sender)
    print(kwargs)
4.3.3、内置信号总结
# 方式一
# 导入内置信号
from django.core.signals import request_started
# 定义一个函数
def aa(sender, **kwargs):
    print(sender)
    print(kwargs)
    print('请求来了,记录日志...')

# 跟内置信号绑定
request_started.connect(aa)

# 方式二
from django.core.signals import request_started, request_finished
from django.dispatch import receiver
@receiver(request_finished)  # 内置信号pre_save和my_callback函数绑定了
def my_callback(sender, **kwargs):
    print("请求离开,走了我")

你可能感兴趣的:(python,python,django)