一、权限组件的使用

# 用户信息表
class UserInfo(models.Model):
name = models.CharField(max_length=32)
# 写choice
user_choice=((0,'普通用户'),(1,'会员'),(2,'超级用户'))
# 指定choice,可以快速的通过数字,取出文字
user_type=models.IntegerField(choices=user_choice,default=0)
pwd = models.CharField(max_length=32) # 用户token
class UserToken(models.Model):
token = models.CharField(max_length=64)
user = models.OneToOneField(to=UserInfo)

1、使用语法

from rest_framework.permissions import BasePermission

# 写一个权限类
class UserPermission(BasePermission):
# 重写没有权限时的数据
message = '您没有权限'
# 重写has_permission()方法,传入三个参数
# 第一个是对象自身(自动传);第二个是request对象;第三个是
def has_permission(self, request, view):
# 只要认证通过,就会把当前用户对象放到request中
user_type = request.user.user_type
# get_字段名_display() 可以获取choice数字对应的具体值
# user_type_name = request.user.get_user_type_display()
# print(user_type_name)
if user_type == 2:
return True
return Fals
class Book(APIView):
# 用户认证
authentication_classes = [UserAuth.UserAuth, ]
# 权限判断
permission_classes = [MyPerm.UserPermission, ] def get(self, request, *args, **kwargs):
response = {'status': 100, 'msg': '查询成功'}
ret = models.Book.objects.all()
ser = MySerializer.BookSerializer(instance=ret, many=True)
response['data'] = ser.data
return JsonResponse(response, safe=False)

2、全局使用、局部使用、局部禁用权限

(1)全局使用

  • 在settings文件中配置,配置完以后,就无需在视图类中写,已经是所有视图类都需要权限判断
  • 必须为REST_FRAMEWORK,key值必须为DEFAULT_AUTHENTICATION_CLASSES
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES':['app01.MyPerm.UserPermission',],
}

(2)局部使用

在需要使用的视图类中写,只对当前视图类起认证作用,重新定义permission_classes

class Book(APIView):
# # 该方法是局部使用认证
authentication_classes = [UserAuth.UserAuth, ]
# 该方法是局部使用权限
permission_classes = [MyPerm.UserPermission, ] def get(self, request, *args, **kwargs):
response = {'status': 100, 'msg': '查询成功'}
ret = models.Book.objects.all()
ser = MySerializer.BookSerializer(instance=ret, many=True)
response['data'] = ser.data
return JsonResponse(response, safe=False)

(3)局部禁用

在配置过全局权限判断以后,有些视图类不需要判断权限,可以局部禁用权限证,只需将permission_classes定义为空列表即可。

class Book(APIView):
# # 该方法是局部使用认证
authentication_classes = [UserAuth.UserAuth, ]
# 该方法是局部禁用权限
permission_classes = [] def get(self, request, *args, **kwargs):
response = {'status': 100, 'msg': '查询成功'}
ret = models.Book.objects.all()
ser = MySerializer.BookSerializer(instance=ret, many=True)
response['data'] = ser.data
return JsonResponse(response, safe=False)

二、源码分析

as_view ----------> view -------------> dispatch -------> Request包装新的request ------> 认证、权限、频率 --------> 根据请求方式分发到不同的方法

1、Book中没有as_view

2、APIView的as_view

class APIView(View):

    @classmethod
# cls 是 Book类
def as_view(cls, **initkwargs): # view = super(APIView, Book).as_view(**initkwargs)
view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)

3、view = super(APIView, cls).as_view(**initkwargs) ---------------------> View中的as_view

class View(object):

    @classonlymethod
# cls====> Book
def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
# 实例化产生一个book对象
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# 调dispatch方法
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs # take name and docstring from class
update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view

4、return self.dispatch(request, *args, **kwargs) ----------------> dispatch

self====> Book对象,一层层找dispatch

APIView中找到dispatch

class APIView(View):

    def dispatch(self, request, *args, **kwargs):

        self.args = args
self.kwargs = kwargs # (a)初始化request,就是通过Request类来包装原生request,得到包装后的request
request = self.initialize_request(request, *args, **kwargs)
# 从现在开始request就是包装后的request
self.request = request
self.headers = self.default_response_headers # deprecate? try:
# (b) 认证、权限、频率
self.initial(request, *args, **kwargs) # Get the appropriate handler method
# http_method_names表示列表['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

(a)request = self.initialize_request(request, *args, **kwargs) 包装 request

self 是Book对象

class APIView(View):
# 默认的认证列表类
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
# (a-b)实例化初始化产生新的request对象
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), # 认证类实例化产生的对象的列表
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
    def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes]
(a------1)return Request( ··· ) ----------> Request类初始化
    def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
) self._request = request
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty if self.parser_context is None:
self.parser_context = {}
self.parser_context['request'] = self
self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET force_user = getattr(request, '_force_auth_user', None)
force_token = getattr(request, '_force_auth_token', None)
if force_user is not None or force_token is not None:
forced_auth = ForcedAuthentication(force_user, force_token)
self.authenticators = (forced_auth,)

(b)self.initial(request, *args, **kwargs) -----> 认证、权限、频率

    def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
# (b------1) 认证
self.perform_authentication(request)
# (b------2)权限
self.check_permissions(request)
# 频率
self.check_throttles(request)
(b------1) self.check_permissions(request) -------> 权限判断
    def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
# (b------1---------1) get_permissions 权限类对象组成的列表
for permission in self.get_permissions():
# 重写的就是这个has_permission()方法,判断当前用户是否有权限
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
(b------1---------1) self.get_permissions() -------> 获取权限类对象组成的列表
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
return [permission() for permission in self.permission_classes]

Django框架(二十)-- Django rest_framework-权限组件的更多相关文章

  1. Django框架(十四)-- forms组件、局部钩子、全局钩子

    一.什么是forms组件 forms组件就是一个类,可以检测前端传来的数据,是否合法. 例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等 二.forms组件的使用 1.使用语 ...

  2. Django框架(十五)—— forms组件、局部钩子、全局钩子

    目录 forms组件.局部钩子.全局钩子 一.什么是forms组件 二.forms组件的使用 1.使用语法 2.组件的参数 3.注意点 三.渲染模板 四.渲染错误信息 五.局部钩子 1.什么是局部钩子 ...

  3. Django框架 之 admin管理工具(组件使用)

    Django框架 之 admin管理工具(组件使用) 浏览目录 激活管理工具 使用管理工具 admin的定制 admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理 ...

  4. 微信小程序把玩(二十八)image组件

    原文:微信小程序把玩(二十八)image组件 image组件也是一个程序不可缺少的,可以这样说一个app中image组件随处可以看到,一般 image有两种加载方式第一种是网络图片第二种是本地图片资源 ...

  5. 微信小程序把玩(二十九)video组件

    原文:微信小程序把玩(二十九)video组件 视频播放组件与图片加载组件也没啥差别,使用起来也没啥注意的 重要属性: wxml <!--监听button点击事件--> <button ...

  6. 微信小程序把玩(二十四)toast组件

    原文:微信小程序把玩(二十四)toast组件 toast消息提示框,可用在提示一些信息,比如清楚缓存给用户一个友好的提示!或操作一些请求不想让用户有什么操作,toast也可以做到因为toast显示时其 ...

  7. 微信小程序把玩(二十五)loading组件

    原文:微信小程序把玩(二十五)loading组件 loading通常使用在请求网络数据时的一种方式,通过hidden属性设置显示与否 主要属性: wxml <!----> <butt ...

  8. 微信小程序把玩(二十六)navigator组件

    原文:微信小程序把玩(二十六)navigator组件 navigator跳转分为两个状态一种是关闭当前页面一种是不关闭当前页面.用redirect属性指定. 主要属性: wxml <naviga ...

  9. Django框架(十二)-- 中间件、CSRF跨站请求伪造

    中间件 一.什么是中间件 请求的时候需要先经过中间件才能到达django后端(urls,views,templates,models) 响应的时候也需要经过中间件才能到达web服务网关接口 djang ...

  10. Django框架(十)--ORM多对多关联关系三种创建方式、form组件

    多对多的三种创建方式 1.全自动(就是平常我们创建表多对多关系的方式) class Book(models.Model): title = models.CharField(max_length=32 ...

随机推荐

  1. Linux 设备树详解【转】

    转自:http://www.pianshen.com/article/428276673/;jsessionid=D90FC6B215155680E0B89A6D060892D4 本文基于天嵌E9V3 ...

  2. Maven中使用tomcat:run出现错误org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException

    配置是正常的.查阅资料以后说是jdk版本什么的问题.多方修改没有任何改观.换一个思路去查询tomcat:run怎么运行. 是因为他还是沿用了上一次的tomcat插件(默认是6)所以运行的时候使用 to ...

  3. Jsoup获取部分页面数据失败 Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml

    用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...

  4. 【Java语言特性学习之四】常用集合

    java中常见的数据结构

  5. Ubuntu 16.04 + OpenCV 自定义环境变量 pkg-config / PKG_CONFIG_PATH

    0. 前言 今天在执行一段脚本的时候,爆出错误: Package opencv was not found in the pkg-config search path. Perhaps you sho ...

  6. 快速了解Electron:新一代基于Web的跨平台桌面技术

    本文引用了作者“ ConardLi”的<用JS开发跨平台桌面应用,从原理到实践>一文部分内容,原文链接:segmentfault.com/a/1190000019426512,感谢原作者的 ...

  7. flask 第一章

    1.安装flask 首先安装python的虚拟环境,每个环境之间的包并不会产生冲突 ,相当于一个单独的 小空间. 由于自己使用的是windows开发环境  所以安装虚拟包的命令如下 pip  inst ...

  8. vue v-html 富文本解析 空格,换行,图片大小问题

    1.保留空格,换行属性 //保留换行空格问题 white-space: pre-wrap; 2.超出部分,强制换行,一般用于数字 //富文本换行 word-wrap: break-word; tabl ...

  9. C# 使用Environment获取当前程序运行环境相关信息

    Enviroment类和AppDomain类前者表示系统级的相关信息,后者表示应用程序级的相关信息. 我常用这两个类获取一些程序运行目录.操作系统位数等信息: string basedir = App ...

  10. Python-- easy_install 的安装

    http://peak.telecommunity.com/dist/ez_setup.py 将这里面的复制出来打包成ez_setup.py 然后cmd到目录下,直接输入ez_setup.py 可能会 ...