• drf 渲染模块


    一、drf按照与使用

    1. 安装drfpip3 install djangorestframework

    2. settings.py注册app:

      INSTALLED_APPS = [
          ...
          'rest_framework'
      ]
      
    3. 基于cbv完成满足restful规范的接口

      # 视图层
      from rest_framework.views import APIView
      from rest_framework.response import Response
      # CBV接口
      class Test(APIView):
          def get(self,request,*args,**kwargs):
              print(request.GET)
              print(request.META)
      
              return Response({
                  'status': 0,
                  'msg': 'get ok'
              })
          
          def post(self,request,*args,**kwargs):
              print(request.POST)
              
              return Response({
                  'status': 0,
                  'msg': 'post ok',
              })
      
      # 路由层
      urlpatterns = [
          url(r'^api/', views.Test.as_view()),
      ]
      

    二、drf CBV源码分析

    • 首先在路由层中注册CBV通过as_view()方法实现CBV,这个和django实现CBV的方法一致。但是drf在CBV中进行了一些其他处理。比如,虽然还是调用的父类的as_view来得到view,但返回时局部禁用了csrf认证csrf_exempt(view)
    • 当请求来的时候,路由视图函数映射关系匹配成功时就会进入请求分发的dispatch()方法.
    • dispatch()方法内在分发执行视图方法前,完成了
      • 二次封装request:self.initialize_request(request, *args, **kwargs)
      • 三大认证:self.initial(request, *args, **kwargs)
    • 在视图方法处理完请求后
      • 出现异常的处理:self.handle_exception(exc)
      • 二次封装response:self.finalize_response(request, response, *args, **kwargs)
    '''rest_framework/views.py -> class APIView(view):中'''
    	@classmethod
        def as_view(cls, **initkwargs):
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    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方法返回view对象
            view = super().as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
            return csrf_exempt(view)
    
    '''rest_framework/views.py -> class APIView(view):中'''
        def dispatch(self, request, *args, **kwargs):
            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)
                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)
            # 二次封装response
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response
    

    注意:接下来大部分关于drf的源码都会从dispatch方法为起点开始分析

    三、请求模块源码分析

    • drf的APIView类:重写了as_view(),但主体逻辑还是调用父类View的as_view(),局部禁用了csrf认证

      重点:所有继承drf的基本视图类APIView的视图类,都不在做csrf认证校验

    • drf的APIView类:重写了dispatch(),在内部对request进行了二次封装

      # 二次封装request
      request = self.initialize_request(request, *args, **kwargs)
      
    • initialize_request方法内部源码分析

      • 返回了Request类的实例化对象。
      • Request类中的__init__方法中将原来的request放到了self._request
      • 所有的拼接参数都解析到query_params中所有数据包数据都被解析到data中,通过@property装饰器将方法属性包装成数据属性。
      • query_params和data属于QueryDict类型,可以通过 .dict() 转化成原生dict类型
    • Request类内部实现了 .拦截方法 __getattr__来取值,可以直接取到_request中的内容

    # CBV接口
    class Test(APIView):
        
        def get(self,request,*args,**kwargs):
            print(request._request.GET) # 直接找原来的request
            print(request.GET)  # 通过内部的getattr来找
            print(request.META) # 通过内部的getattr来找
    
            # QueryDict转化为原生dict
            print(request.query_params.dict())
            # 数据包数据
            print(request.data)
    
            return Response({
                'status': 0,
                'msg': 'get ok'
            })
    
        def post(self,request,*args,**kwargs):
            # 通过内部的getattr来找
            print(request.POST)
    
            # QueryDict转化为原生dict
            print(request.query_params.dict())
            print(request.data.dict())
    
            return Response({
                'status': 0,
                'msg': 'post ok',
            })
    
  • 相关阅读:
    Ruby系列:玩转闭包(Block,Proc,lambda)
    C# 中where关键字【MSDN】
    web应用程序中慎用static变量
    面向对象的javascript(一)
    原型模式 对象深浅复制
    存储过程:异地备份数据库文件
    正则表达式 [笔记]
    连接Oracle数据库代码
    在Eclipse下搭建Android开发环境教程,HelloWord
    Android开发之旅:环境搭建及HelloWorld
  • 原文地址:https://www.cnblogs.com/XuChengNotes/p/11893216.html
Copyright © 2020-2023  润新知