zoukankan      html  css  js  c++  java
  • Django生命周期 URL ----> CBV 源码解析-------------- 及rest_framework APIView 源码流程解析

    一、一个请求来到Django 的生命周期
     
    • FBV 不讨论

    • CBV:
      请求被代理转发到uwsgi:
      开始Django的流程:
      首先经过中间件process_request (session等)
      然后:url --- > Xxx.as_view() 根据url映射到对应业务逻辑类 --->process_view (csrf等)
       
      业务逻辑类中:
      as_view() -- > view ---> dispatch() 通过映射调用请求的方法在业务逻辑中的对应处理函数
      (如post、put、delete等)

    1.2 CBV源码解析
    • 自己的业务逻辑类:MyView 继承View

    • 没有as_view() 方法,将会去父类View找as_view

    class MyView(View):
        
        def get(self, request):
            #处理业务逻辑,返回response
            pass
        
        def post(self, request):
            pass
        
        def put(self, request):
            pass
        
        def delete(self, request):
            pass
    
    1.2.2 View源码中:as_view() 方法被调用
    • 查看as_view 方法源码:作者省略了部分,只留下了关键部分,并做了注释
    class View:
        ...
        @classonlymethod
        def as_view(cls, **initkwargs):
            ...
    
            def view(request, *args, **kwargs):
                ...
                return self.dispatch(request, *args, **kwargs) #调用父类的dispatch() 方法
            ...
    
            return view #返回内部定义的view 方法
    
    

    这儿可以看见:
    1.  as_view()方法被调用,
    2.  内部回返回定义的view 方法,
    3.  view方法中调用了 dispatch() 方法
    4.  如果自己的类没有重写dispatch 方法的话,将会调用父类View类的 dispatche() 方法

    1.2. 查看dispatch方法
     
    • dispatch方法中:作者省略了部分,只留下了关键部分,并做了注释
    class View:
        ...
        def dispatch(self, request, *args, **kwargs):
            ...
            #request.method中保存了客户端解析出来的请求方法,如:GET/POST等
            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
            return handler(request, *args, **kwargs)  #并调用该业务逻辑函数处理结果,将结果返回
    
    • 注意:request.method 保存着解析出来的请求行第一个数据(GET URL HTTP1.1)如:GET

    可以看见:
    1.  if判断客户端请求的方法是否是,http协议(Django)自己支持的
    2.  handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        将请求方法小写,然后在自己的业务类中映射到对应处理函数,如果没有报错
    3.  return handler(request, *args, **kwargs)
        并调用该业务逻辑函数处理结果,将结果返回

    二、rest_framework APIView 流程解析

    先看一个图:给出大致流程

    2.2 APIView中请求流程
    • 同上:请求通过URL 匹配到继承APIView的自己的业务逻辑类。
    class APIView(View):
        ...
        parser_classes = api_settings.DEFAULT_PARSER_CLASSES #默认解析类
        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES #默认认证类
        throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES #默认限流类
        permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES #权限类
        ...
        versioning_class = api_settings.DEFAULT_VERSIONING_CLASS #版本控制获取类
    
        ...
    
        @classmethod
        def as_view(cls, **initkwargs):
            ...
            view = super(APIView, cls).as_view(**initkwargs) #继承父类as_view方法
            view.cls = cls
            view.initkwargs = initkwargs
            ...
            return csrf_exempt(view) #返回父类view
        ...
        def get_parsers(self):
            """
            获取到上面4. 第一步initialize_request函数封装request过程中一并生成封装的解析器对象
            """
            return [parser() for parser in self.parser_classes]
    
        def get_authenticators(self):
            """
            同理身份认证对象
            """
            return [auth() for auth in self.authentication_classes]
    
        def get_permissions(self):
            """
            同理权限对象
            """
            return [permission() for permission in self.permission_classes]
    
        def get_throttles(self):
            """
            同理限流(访问频率控制对象)
            """
            return [throttle() for throttle in self.throttle_classes]
    
        def perform_authentication(self, request):
            ... #这里面真正认证
    
        def check_permissions(self, request):
            ... #这里面检查权限
    
        def check_throttles(self, request):
            ... #这里面限流
     
        def determine_version(self, request, *args, **kwargs):
            ... #这里面获取版本
    
        def initialize_request(self, request, *args, **kwargs):
            """
            被dispatch调用,封装request,并调用上述函数生成相应对象封装到request对象中
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    
        def initial(self, request, *args, **kwargs):
            ...
            被dispatch调用,在里面初始化获取版本,认证、权限检查、访问控制等
    
            # Determine the API version, if versioning is in use.
            #处理版本问题,调用 determine_version方法
            version, scheme = self.determine_version(request, *args, **kwargs)
            request.version, request.versioning_scheme = version, scheme
    
            # Ensure that the incoming request is permitted
            #3.在这儿实现认证
            self.perform_authentication(request)
            #4.权限检查
            self.check_permissions(request)
            #5.访问频率控制
        
        ...
    
        def dispatch(self, request, *args, **kwargs):
            ...        
            self.args = args
            self.kwargs = kwargs
            ##############################################################
            # 1.封装request
            request = self.initialize_request(request, *args, **kwargs)
            ##############################################################
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                ##############################################################
                #2.认证
                self.initial(request, *args, **kwargs)
                ##############################################################
                # Get the appropriate handler method
                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
    

    如下步骤对应上述省略部分的源代码去找:

    1. 找as_view()函数
    第一步自己业务逻辑类中:没有,
    第二步父类-APIView中:找到as_view方法,开始调用

    2. APIView继承了View,APIView的as_view函数继承了父类as_view:如下为源码
    view = super(APIView, cls).as_view(**initkwargs) #继承父类的as_view
    view.cls = cls #把自身封装进去
    view.initkwargs = initkwargs #将参数初始化
    return csrf_exempt(view) #返回view
    可以看见封装了一次as_view方法,将自身cls (APIView)一起封装到了view中
    并返回

    3. 通过上面1-2 知道:继承请求进入后会调用返回的view方法,然后在self中找dispatch方法,
    第一步自己的业务逻辑类中:没有dispatch
    第二步父类APIView中:找到dispatch方法,开始调用

    4. APIView的dispatch 函数中:
    第一步:request = self.initialize_request(request, *args, **kwargs) 封装了一次request
     
    initialize_request函数内如下:
    return Request(
    request, #原生request
    parsers=self.get_parsers(), #解析器
    authenticators=self.get_authenticators(), #身份验证器
    negotiator=self.get_content_negotiator(),
    parser_context=parser_context
    )
    第二步:self.initial(request, *args, **kwargs) 开始初始化认证
     
    initial函数内:
    1)获取版本,版本处理类实例。并封装到request中
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme
     
    2)身份(登录)认证啥的
    self.perform_authentication(request)
     
    3)权限管理
    self.check_permissions(request)
     
    4)限流控制(访问频率控制)
    self.check_throttles(request)

    2.2.3 上述总结
    1. 首先找dispatch 函数(APIView类中)

    2. dispatch中:
      调用了self.initialize_request 函数封装request

    3. 接着2的dispatch中initialize_request 函数
      查看APIView中的initialize_request 函数
      调用了:get_parsers()、get_authenticators() 等
      封装了一堆解析器类实例、认证类实例啥的
      可自己去看(这些类使用默认配置,APIView 一开头下面一堆配置就是)
      这些类也可以自己写,配置到自己的业务逻辑类中,或者settings.py中作为全局配置(下面在讲)

    4. 接着2的dispatch中initial函数
      版本获取:
      version, scheme = self.determine_version(request, *args, **kwargs)
      request.version, request.versioning_scheme = version, scheme
      实现认证
      self.perform_authentication(request)
      权限检查
      self.check_permissions(request)
      访问频率控制
      self.check_throttles(request)

    三、常用的解析、认证、权限、访问频率控制源码及解析

    from rest_framework.views import APIView #继承类路径
    from rest_framework import request #dispatch中initialize_request封装的request对象

    from rest_framework.parsers import JSONParser, FormParser, FileUploadParser #不同解析器
    from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning #两种版本获取器
    from rest_framework.authentication import BaseAuthentication #登录验证
    from rest_framework.permissions import BasePermission #权限
    from rest_framework.throttling import SimpleRateThrottle #节流
    from rest_framework import exceptions #错误

  • 相关阅读:
    Spring IoC和AOP使用扩展(二)
    Spring核心概念(一)
    MyBatis的动态SQL(五)
    MyBatis的SQL映射文件(四)
    初始myBatis(三)
    初始myBatis(二)
    微信小程序学习九 事件系统
    微信小程序学习八 wxs
    微信小程序学习七 视图层wxml语法
    微信小程序学习六 模块化
  • 原文地址:https://www.cnblogs.com/shiqi17/p/9858103.html
Copyright © 2011-2022 走看看