drf学习笔记
今日内容概要
- 排序和过滤源码分析
- 基于jwt的认证类
- RABC的介绍和使用
- ACL、RBAC、ABAC(PBAC,CBAC)权限控制的介绍
- 后台管理simplui的介绍和使用
今日内容详细
排序和过滤源码分析
继承了GenericAPIView+ListModelMixin,只要在视图类中配置filter_backends它就能实现过滤和排序。
1. drf内置的过滤类(SearchFilter),排序类(OrderingFilter)
2. 第三方类:django-filter
3. 自定义:写一个类,继承BaseFilterBackend,重写filter_queryset,返回的qs对象,就是过滤或排序后的
# 只有获取多个才涉及到排序
1. 首先只有 list方法是获取全部,找到ListModelMixin下的 list方法。
def list(self, request, *args, **kwargs):
# self.get_queryset()所有数据,经过了self.filter_queryset返回了qs
# self.filter_queryset完成的过滤
queryset = self.filter_queryset(self.get_queryset())
# 如果有分页,走的分页----》视图类中配置了分页类
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
# 如果没有分页,走正常的序列化,返回
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
2. self.filter_queryset完成了过滤,当前在视图类中,self是视图类的对象,去视图类中找没找到,去父类 GenericAPIView 中找到filter_queryset方法。
def filter_queryset(self, queryset):
for backend in list(self.filter_backends): # 循环拿到你写的过滤类
# 过滤类对象调用filter_queryset方法(4个参数)
# self(过滤类对象),request,queryset,self(视图类)
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
总结:
1. 写的过滤类要重写filter_queryset,返回qs(过滤或排序后)对象
2. 后期如果不写过滤类,只要在视图类中重写filter_queryset,在里面实现过滤也可以
基于jwt的认证类
from rest_framework_jwt.settings import api_settings
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
class JWTAuthentication(BaseAuthentication):
def authenticate(self, request):
# 放到头中:token-->HTTP_TOKEN Authorization--->HTTP_AUTHORIZATION
# print(request.META)
jwt_value = request.META.get('HTTP_TOKEN')
# 验证token是否合法,jwt模块下一定有个验证token的函数
try:
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
raise AuthenticationFailed('token过期了')
except jwt.DecodeError:
raise AuthenticationFailed('token解码失败')
except jwt.InvalidTokenError:
raise AuthenticationFailed('认证失败')
# 执行到这,说明token合法,payload可以使用
user_id = payload.get('user_id')
user = UserInfo.objects.filter(pk=user_id).first() # 每次都要查数据库,效率不太好
return (user, jwt_value)
# return (payload,jwt_value)
RBAC的介绍和使用
RBAC 是基于角色的访问控制(Role-Based Access Control )在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
# RBAC权限管理的模式,最适合公司内部的管理系统,不适合对外互联网用户的系统
用户:用户表
角色(部门):角色表(部门表)
权限:权限表
# 表的作用:
权限:所有权限都是存在权限表中一条条的记录(发工资,招聘员工,开员工,发布新版本,开董事会)
角色(部门):权限是授予角色的(部门的),一个个角色,就是一条条记录(开发角色,hr角色,股东角色)
用户:一个个用户是用户表中一条条记录,用户属于某个部门
# 三个表之间的关系:
用户和角色关系:多对多,中间表
角色和权限关系:多对多,中间表
# 一共有 5张表:
用户表
角色表
权限表
用户和角色关联表
角色和权限关联表
例子:
用户表: 角色表: 权限表:
id 姓名 id 角色名称 id 权限名词
1 张三 1 hr角色 1 发工资
2 李四 2 股东角色 2 招人
3 王五 3 开发角色 3 提交代码
# 给张三提交代码的权限
用户和角色中间表: 权限和角色的中间表:
id 角色id 用户id id 角色id 权限id
1 3 1 2 3 3
# django的后台管理admin就自带了rbac的权限,通过auth模块实现的,比普通rbac更高级一些
django是6张表,用户和权限的多对多关系表(一个用户可以分配多个权限,一个权限可以给多个用户)
用户表
角色表
权限表
用户和角色关联表
角色和权限关联表
用户和权限关联表
启用了admin和auth,这6张表就迁移进去了:
auth_user # 用户表
auth_group # 角色,组,部门表
auth_permission # 权限表
auth_user_groups # 用户和角色中间表
auth_group_permissions # 角色跟权限中间表
auth_user_user_permissions#用户和权限的中间表
之前很多公司写后台管理使用dajngo,使用django的admin二次开发,不用写权限了,快速加功能即可。
ACL、RBAC、ABAC(PBAC,CBAC)权限控制的介绍
# ACL(Access Control List,访问控制列表)
将用户或组等使用者直接与对象的权限对接。
用户表,权限表,中间表 给用户授予某些权限即可
# RBAC(Role-Based Access Control,基于角色的访问控制)
将用户与角色对接,然后角色与对象的权限对接
# RBAC+ACL django,公司用的比较多啊
# ABAC(Attribute-Based Access Control,基于属性的访问控制)
ABAC(Attribute-Based Access Control,基于属性的访问控制),
又称为PBAC(Policy-Based Access Control,基于策略的访问控制),
CBAC(Claims-Based Access Control,基于声明的访问控制)。
传统的ACL、RBAC的架构是{subject,action,object},
而ABAC的架构是{subject,action,object,contextual}且为他们添加了parameter(参数)。
subject属性:比如用户的年龄、部门、角色、威望、积分等主题属性。
action属性:比如查看、读取、编辑、删除等行为属性。
object属性:比如银行账户、文章、评论等对象或资源属性。
contextual属性:比如时段、IP位置、天气等环境属性。
例子:
权限表:
id 权限名
1 开除员工
id 权限名 属性
1 开除员工 女
1 开除员工 男
casbin:方便我们快速做权限控制(acl,rbac...)
使用详情链接:https://docs.casbin.cn/zh/docs/get-started
import casbin
e = casbin.Enforcer("./model.conf", "./policy.csv")
sub = "lqz" # 想要访问资源的用户
obj = "book" # 将要被访问的资源
act = "get" # 用户对资源进行的操作
# 自己写acl的控制
# 当前用户id,去权限和用户表查询即可,有记录就是有权限
# 自己写rbac
# 当前用户id,找到他的角色,根据角色拿出权限,判断当前访问有没有
if e.enforce(sub, obj, act):
# 允许alice读取data1
print('有权限')
else:
# 拒绝请求,抛出异常
print('没有权限')
model.conf
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
policy.csv
p,alice,data1,read
p,bob,data2,write
p,lqz,book,get
后台管理simplui的介绍和使用
simpleui 是django admin的一个主题 是一个基于element-ui+vue开发,重写和优化90%以上的页面。 与suit是同类产品。我们是一个更符合国人审美和使用习惯的一个主题。
安装
pip3 install django-simpleui
启用:只需要在项目中的settings.py文件中加入一行simpleui即可。
# Application definition
INSTALLED_APPS = [
'simpleui',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
...
]
使用详情链接:https://simpleui.72wo.com/docs/simpleui/quick.html
settings.py
import time
SIMPLEUI_CONFIG = {
'system_keep': False,
'menu_display': ['我的首页', '图书管理','权限认证', '多级菜单测试', '动态菜单测试'], # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
'dynamic': True, # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
'menus': [
{
'name': '我的首页',
'icon': 'fas fa-code',
'url': '/index/',
},
{
'app': 'app01',
'name': '图书管理',
'icon': 'fas fa-code',
'models': [
{
'name': '用户',
'icon': 'fa fa-user',
'url': 'app01/userinfo/'
},
{
'name': '图书',
'icon': 'fa fa-user',
'url': 'app01/book/'
},
{
'name': '出版社',
'icon': 'fa fa-user',
'url': 'app01/publish/'
},
]
},
{
'app': 'auth',
'name': '权限认证',
'icon': 'fas fa-user-shield',
'models': [{
'name': '用户',
'icon': 'fa fa-user',
'url': 'auth/user/'
}]
},
{
# 自2021.02.01+ 支持多级菜单,models 为子菜单名
'name': '多级菜单测试',
'icon': 'fa fa-file',
# 二级菜单
'models': [
{
'name': '百度',
'icon': 'far fa-surprise',
# 第三级菜单 ,
'models': [
{
'name': '爱奇艺',
'url': 'https://www.iqiyi.com/dianshiju/'
# 第四级就不支持了,element只支持了3级
},
{
'name': '百度问答',
'icon': 'far fa-surprise',
'url': 'https://zhidao.baidu.com/'
}
]
},
{
'name': 'lqz',
'url': 'https://www.wezoz.com',
'icon': 'fab fa-github'
}]
},
{
'name': '动态菜单测试',
'icon': 'fa fa-desktop',
'models': [{
'name': time.time(),
'url': 'http://baidu.com',
'icon': 'far fa-surprise'
}]
}]
}
SIMPLEUI_LOGIN_PARTICLES = False
SIMPLEUI_HOME_INFO = False
admin.py
from django.contrib import admin
# Register your models here.
from .models import *
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('id', 'title', 'price')
# 增加自定义按钮
actions = ['make_copy', ]
def make_copy(self, request, queryset):
print('adsfasdf')
make_copy.short_description = '自定义按钮'
# # icon,参考element-ui icon与https://fontawesome.com
make_copy.icon = 'fas fa-audio-description'
# # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
make_copy.type = 'danger'
make_copy.confirm = '你是否执意要点击这个按钮?'
admin.site.register(UserInfo)
admin.site.register(Publish)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了