Django框架(二十一)—— Django rest_framework-权限组件

Django rest_framework-权限组件

一、权限组件的使用

# 用户信息表
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 False
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 ------> 认证、权限、频率 --------> 根据请求方式分发到不同的方法

url(r'books/',views.Book.as_view())

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]
博客内容仅供参考,部分参考他人优秀博文,仅供学习使用

转载于:https://www.cnblogs.com/zhuzhiwei-2019/p/10779209.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值