zoukankan      html  css  js  c++  java
  • request请求生命周期

    request请求生命周期

    一、request请求分析

    1.1. request数据请求

    # views.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from django.http.request import QueryDict
    class BookAPIView(APIView):
    
        def get(self, request, *args, **kwargs):
            print(request._request.GET)  # 原生wigs中值
            print(request.GET) # 二次封装的值
            print(request.META) # 所有get请求信息
            print(request.META.get("HTTP_AUTH")) # 前台发来的头都会大写并加上HTTP
            print(request.query_params) # 所有url数据
            
            print(request.POST) # get请求不能获取Post请求数据
    
            return Response('get ok')
    
        def post(self, request, *args, **kwargs):
            print(request._request.POST)  # 原生wigs中值
            print(request.POST) # 二次封装的值
            print(request.data) # 所有post请求数据
            print(request._request) # url数据包<WSGIRequest: POST '/books/?age=123'>
            print(request.GET) # POST请求可以Post请求数据
                
             # QueryDict转为
            print(request.query_params.dict())
            if isinstance(request.data, QueryDict):
                print(request.data.dict())
    
            return Response('post ok')
        
        
        
    # urls.py
    from . import views
    urlpatterns = [
        url(r'^books/$', views.BookAPIView.as_view()),
    ]
    
    

    img

    总结:

    1. drf中的request是在wsgi的request基础上进行再一次封装
    2. 将wsgi的request作为drf的request的一个属性, _request
    3. drf中的request对wsgi中的request做完全兼容,新的可以直接获取wsgi中的数据
    4. drf中的request对数据解析更规范化,所有的拼接参数(url?age=18)都解析到了query_params中,所有数据报数据都解析到data中
    5. query_params和data属于QueryDict类型,可以通过.dict()转化为字典类型

    二、request请求源码分析

    # 1. 2. urls.py
    from . import views
    urlpatterns = [
        url(r'^books/$', views.BookAPIView.as_view()),
    ]
    
    #3.调用drf中的as_view
    @classmethod
    def as_view(cls, **initkwargs):     # cls 为 views.BookAPIView类
        ...
        view = super().as_view(**initkwargs) # as_view原生的as_view,super() 为 view
        view.cls = cls
        view.initkwargs = initkwargs
    
        return csrf_exempt(view)
    # 4.进入drf中dispatch 
    def dispatch(self, request, *args, **kwargs):   # self为views.BookAPIView类
        self.args = args  
        self.kwargs = kwargs
        # 对原生request进行了二次封装
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            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
                    
    # 4.1 返回封装的request对象
    def initialize_request(self, request, *args, **kwargs):
        """
            Returns the initial request object.
            """
        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
        )
    # 5.Request类创建 self._request = request自己的属性
     def __init__(self, request, parsers=None, authenticators=None,
                     negotiator=None, parser_context=None):
            assert isinstance(request, HttpRequest), (
               
                .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
            
    #6.如何实现获取wgis中的属性
    def __getattr__(self, attr):   
        """
            If an attribute does not exist on this instance, then we also attempt
            to proxy it to the underlying HttpRequest object.
            """
        try:
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
    

    img

    1. 导入drf中的APIView并创建类继承它,在配置url: url(r'^books/$', views.BookAPIView.as_view()),

    2. 当项目启动时会执行drf中的as_view()方法,返回view方法(局部禁用了csrf认证), url:url(r'^books/$', views.BookAPIView.view

    3. 浏览器发送请求来时则会执行url中view函数,在执行view中返回的是 self.dispatch(request, *args, **kwargs), dispatch是drf中的dispatch, 不是wsgi中原生的dispatch

    4. 进入drf中的dispatch首先会对原生的request进行二次封装:request = self.initialize_request(request, *args, **kwargs),在initialize_request方法中返回了一个request实例对象

    5. 进入request.py中的Request方法中就会发现在初始化方法中将wsgi方法的request变为了自己的一个属性: 'self._request = request'

    6. request通过反射的方法获取wsgi中request属性,当request.获取属性先到 _request中查找,没有则查自己本身的

      #6.如何实现获取wgis中的属性
      def __getattr__(self, attr):   
          """
              If an attribute does not exist on this instance, then we also attempt
              to proxy it to the underlying HttpRequest object.
              """
          try:
              return getattr(self._request, attr)
          except AttributeError:
              return self.__getattribute__(attr)
      
    7. 核心

      • 走drf的Request初始化方法__init__:self._request = request
      • drf的Request的getter方法__getattr__:先从self._request反射取属性,没取到再从drf的request中取
      • request除了可以访问原wsgi协议的request所有内容,还可以访问 query_params、data
  • 相关阅读:
    Centos7.3防火墙配置
    Centos7使用yum安装MySQL5.6的正确姿势
    Connect C# to MySQL
    ADO.NET操作MySQL数据库
    Mac OS 上 VIM 8.0 安装体验
    WebSocket实战之————Workerman服务器的安装启动
    C语言实现文件复制功能(包括文本文件和二进制文件)
    Gateway/Worker模型 数据库使用示例
    [转]Using the Group Pane to Repeat Page Titles
    [转]学习 WCF (6)--学习调用WCF服务的各种方法
  • 原文地址:https://www.cnblogs.com/randysun/p/12290077.html
Copyright © 2011-2022 走看看