zoukankan      html  css  js  c++  java
  • APIView源码解析

    APIView源码解析:

    class APIView(View):

    过程:

    从as_view()方法开始,创建一个实例,再调用dispatch()方法,dispatch()方法里面也有五步,分别是:记录各个参数,初始化请求方法(initialize_request()),initial()方法,根据得到的请求方法去处理或处理异常,最后统一处理response。初始化请求方法里面构建了一个新的request,在request里边获取了输入转换器,认证器,内容决策器和输入内容,initial方法里边又去执行内容决策,确定决策版本,执行认证,检查权限,检查节流,然后在去处理请求方法,所以在dispatch()方法中initial里边,它帮我们执行了认证和检查权限和检查节流,所以我们只要在类中使用restframework框架中的APIView类,然后写视图函数,调用as_view()方法就可以做到认证和节流了。这就是这个restframework框架给开发者带来的好处,就很方便我们去维护代码。

    从入口开始看代码:

    as_view():

        @classmethod
        def as_view(cls, **initkwargs):
            # 如果他是QuerySet的一个实例
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    # 翻译:不要直接计算“.queryset”属性,因为结果将被缓存并在请求之间重用请改用“.all()”或调用“.get_queryset()”
                    raise RuntimeError(
                        'Do not evaluate the `.queryset` attribute directly, '
                        'as the result will be cached and reused between requests. '
                        'Use `.all()` or call `.get_queryset()` instead.'
                    )
                # 强制性把属性拿过来
                cls.queryset._fetch_all = force_evaluation
                
    	# 该走这里了,调用父类的as_view() --- 父类的as_view()核心是dispatch()  >> 跳转到dispatch()
            view = super().as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
    
            # Note: session based authentication is explicitly CSRF validated,
            # all other authentication is CSRF exempt.
            
            # 豁免csrf检测, 返回view
            return csrf_exempt(view)	 # 函数里面套函数,这个一个装饰器!!!
        
    

    意外收获:

    # FBV中调用的函数不能使用post请求,否则会出现403跨域请求,把装饰器放在函数上可以豁免csrf检测
    
    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def index(request):
        return HttpResponse("嘿嘿,我还是进来了!")
    

    as_view()的核心是dispatch() >>

    dispatch():

    1. 记录各个参数
    2. initializer_request() <<
    3. initial <<
    4. 根据得到的请求方法去处理,或处理异常
    5. 最后统一处理response
    # 源码
    	def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
            # 跳转看一看 >> initializer_request()
            request = self.initialize_request(request, *args, **kwargs)
            
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                # 再跳一跳 >> initial()
                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
    

    dispatch() >> initialize_request()

    initialize_request():

    1. 获取文本
    2. 使用Django中的request构建了一个新的request。
    3. 获得了输入转换器,认证器,内容决策器,输入的内容
    # 源码
    	def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            # 解析上下文
            parser_context = self.get_parser_context(request)
            
    	# 构建了一个新的request
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    

    dispatch() >> initial()

    initial(): --- 核心

    1. 获取格式化后缀
    2. 执行内容决策
    3. 拆包
    4. 进行决策版本,确定版本
    5. 执行认证(重点)
    6. 检查权限
    7. 检查节流
    #源码
        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
            # 执行认证,检查权限,检查节流
            self.perform_authentication(request)
            self.check_permissions(request)
            self.check_throttles(request)
    

    APIView所有方法:

  • 相关阅读:
    Java开发web的几种开发模式
    Tomcat7.0安装配置
    Apache与Tomcat 区别联系
    编写 Window 服务程序
    系列文章--SharePoint 开发教程
    Google Chrome浏览器调试功能介绍
    Chrome的JS调试工具
    Google Chrome 调试JS简单教程[更新]
    ASP.NET常用标准配置web.config
    WINDOWS下kill进程的命令
  • 原文地址:https://www.cnblogs.com/lance-lzj/p/13853064.html
Copyright © 2011-2022 走看看