zoukankan      html  css  js  c++  java
  • day71

    rest_framework框架的封装特点

    import rest_framework
    from rest_framework.views import APIView
    from rest_framework.request import Request
    
    
    在views.py中写出合适的api类,只需要继承rest_framework中generics中的某个类,重写我们需要的方法实现合适的逻辑即可
    

    APIView请求生命周期

    APIView的as_view(局部禁用csrf)
    =>走父级的as_view调用dispatch分发请求
    =>APIView自己重写了dispatch,使用自己完成分发
    =>分发前完成request二次封装、数据解析
    =>三大认证
    =>请求的实际响应(自己的视图类的处理分发)
    =>出现了异常,就会交给异常模块处理异常
    =>响应模块完成响应、渲染模块可以以json或浏览器两种方式渲染
    
    APIView请求生命周期
    1)APIView类继承View类,重写了as_view和dispatch方法
    2)重写的as_view方法,主体还是View的as_view,只是在返回视图view函数地址时,局部禁用csrf认证
    3)在执行请求逻辑前:请求模块(二次封装request)、解析模块(三种数据包格式的数据解析)
    在执行请求逻辑中:异常模块(执行出任何异常交给异常模块处理)
    在执行请求逻辑后:响应模块(二次封装response)、渲染模块(响应的数据能JSON和页面两种渲染)
    

    https://images.cnblogs.com/cnblogs_com/gfhh/1620029/t_191224131554APIView请求生命周期.png

    请求模块

    request._request 被request完全兼容
    request.query_params | request.data
    
    1)将wsgi的request对象转化成drf的Request类的对象
    2)封装后的request对象完全兼容wsgi的request对象,并且将原request保存在新的request._request
    3)重写格式化请求数据存放位置
    	拼接参数:request.query_params
    	数据包参数:request.data
    
    源码解析:
    入口:APIVIew的dispatch方法的request=self.initialize_request(request,*args,**kwargs)
    print(request._request.method)		在内部将wsgi的request赋值给request._request
    print(request.method)				就是通过__getattr__走的是request._request.method
    print(request.query_params)   		走的是方法属性,就是给request._request.GET重新命名
    print(request.data)					走的是方法属性,值依赖于request._full_data
    

    解析模块

    解析模块:只处理数据包参数  -form-data,urlencoded,json
    局部配置:parser_classes = [JSONParser, FormParser, MultiPartParser]
    全局配置:
    	'DEFAULT_PARSER_CLASSES': [
                'rest_framework.parsers.JSONParser',
                'rest_framework.parsers.FormParser',
                'rest_framework.parsers.MultiPartParser'
            ],
    
    1)全局配置所有视图类的解析方式,解析配置可以配置三种
    2)局部配置当前视图类的解析方式,解析配置可以配置三种
    3)配置的查找顺序:局部(视图类的类属性) =>全局(settings文件的drf配置)=>默认(drf的默认配置)
    
    注:该模块了解,但是全局局部配置是重点
    REST_FAMEWORK = {
    	全局配置解析类:适用于所有视图类
    	'DEFAULT_PARSER_CLASSES': [
    	#'rest_framework.parsers.JSONParser',
    	#'rest_framework.parsers.FormParser',
    	#'rest_framework.parsers.MultiPartParser'
    	],
    }
    
    源码解析:
    入口:APIVIew的dispatch方法的 request=self.initialize_request(request,*args,**kwargs)
    获取解析类:parsers = self.get_parsers(),
    进行局部全局默认配置查找顺序进行查找:return [parser() for parser in self.parser_classes]
    

    响应模块

    Response(data=常量|列表|字典,status=网络状态码)
    
    data:响应数据
    status:响应的网络状态码
    template_name:drf完成前后台不分离返回页面,但是就不可以返回data(不需要了解)
    headers:响应头,一般不规定,走默认
    exception:一般异常响应,会将其设置成True,默认False(不设置也没事)
    content_type:默认就是 application/json,不需要处理
    

    渲染模块

    局部配置:renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
    全局配置:
    		'DEFAULT_RENDERER_CLASSES': [
            	'rest_framework.renderers.JSONRenderer',
            	'rest_framework.renderers.BrowsableAPIRenderer',  # 上线后尽量关闭
        	],
    
    渲染模块(了解):Postman请求结果是json,浏览器请求结果是页面
    可以全局与局部配置
    
    • 局部配置解析类:只适用于当前视图类

      parser_classes = [JSONParser, FormParser, MultiPartParser]
      
    • 局部配置渲染类:只适用于当前视图类

      renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
      
          def post(self, request, *args, **kwargs):
              print(request._request.method)  # 在内部将wsgi的request赋值给request._request
              print(request.method)  # 就是通过__getattr__走的是request._request.method
              print(request.query_params) # 走的是方法属性,就是给request._request.GET重新命名
              print(request.data)  # 走的是方法属性,值依赖于request._full_data
      
              return Response({
                  'msg': 'apiview post ok'
              })
      

    异常模块

    settings中配置:'EXCEPTION_HANDLER': 'api.exception.exception_handler',
    重写exception_handler方法:
    
    一定要在settings文件中将异常模块配置自己的异常处理函数
    from rest_framework.views import exception_handler as drf_exception_handler
    from rest_framework.response import Response
    
    先交个drf处理客户端异常,如果结果response代表服务器异常,自己处理
    最终一定要在日志文件中记录异常现象
    def exception_handler(exc, context):
        response = drf_exception_handler(exc, context)
        detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc)
        if not response:  # 服务端错误
            response =  Response({'detail': detail})
        else:
            response.data = {'detail': detail}
            
        核心:要将response.data.get('datail')信息记录到日志文件
        logger.waringz(response.data.get('datail'))
        
        return response
    
    源码解析:
    入口:APIVIew的handle_exception方法的 
    获取异常函数:exception_handler = self.get_exception_handler()
    提供额外参数:context = self.get_exception_handler_context()
    默认的exception_handler函数只处理客户端异常形成的response对象,
    服务器异常不做处理
    二次封装过后的response,处理了结果渲染
    

    原生的Django与drf比较:drf不受csrf认证限制

    from django.views import View
    from django.http import JsonResponse
    class BookView(View):
        def get(self, request, *args, **kwargs):
            return JsonResponse({
                'msg': 'view get ok'
            })
        def post(self, request, *args, **kwargs):
            return JsonResponse({
                'msg': 'view post ok'
            })
            
    -----------------------------------------------
    from rest_framework.views import APIView
    from rest_framework.response import Response
    class BookAPIView(APIView):
        def get(self, request, *args, **kwargs):
            return Response({
                'msg': 'apiview get ok'
            })
        def post(self, request, *args, **kwargs):
            return Response({
                'msg': 'apiview post ok'
            })
    
    settings文件中一定要注册drf
    
    INSTALLED_APPS = [
        'rest_framework',
    ]
    
    drf框架自定义配置
    REST_FAMEWORK = {
    	全局配置解析类:适用于所有视图类
    	'DEFAULT_PARSER_CLASSES': [
    	#'rest_framework.parsers.JSONParser',
    	#'rest_framework.parsers.FormParser',
    	#'rest_framework.parsers.MultiPartParser'
    	],
    	全局配置渲染类:适用于所有视图类
    	    'DEFAULT_RENDERER_CLASSES': [
    	    'rest_framework.renderers.JSONRenderer',
    	    #'rest_framework.renderers.BrowsableAPIRenderer', 上线尽量关闭
    	    ],
    	    异常模块:异常处理函数
    	    # 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
        	'EXCEPTION_HANDLER': 'api.exception.exception_handler',
    }
    

    在api文件夹中新建exception文件

    一定要在settings文件中将异常模块配置自己的异常处理函数
    from rest_framework.views import exception_handler as drf_exception_handler
    from rest-framework.response import Rseponse
    
    def exception_handler(exc, context):
        response = drf_exception_handler(exc, context)
        detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc)
        if not response: 服务器错误
        	response  = Rseponse({'detail':detail})
        else:
        	response.data = {'detail':detail}
        	
        核心:要将response.data.get('detail')信息记录到日志中
        logger.waring(response.data.get('detail'))
        return response
    
    utils文件夹下的views.py文件
    def handle_exception(self,exc):
    
    """
    Handle any exception that occurs, by returning an appropriate response,
    or re-raising the error.
    处理任何发生的异常,通过返回适当的响应,
    或重新引发错误。
    """
    
    出现三大认证相关异常,额外处理一下响应头
    if isinstance(exc, (exceptions.NotAuthenticated,
                                exceptions.AuthenticationFailed)):
                                
     # WWW-Authenticate header for 401 responses, else coerce to 403
                auth_header = self.get_authenticate_header(self.request)
    
                if auth_header:
                    exc.auth_header = auth_header
                else:
                    exc.status_code = status.HTTP_403_FORBIDDEN
                    
    获取出来异常的函数:该文件独立存在的exception_handler函数
    exception_handler = self.get_exception_handler()
    
    给异常处理提供额外的参数
    context = self.get_exception_handler_context()
    
    exc异常对象,context中用视图对象和请求对象
    response = exception_handler(exc,context)
    
    默认的exception_handler函数只处理客户端异常形成response对象,服务器异常不做处理,返回None
    if response is None:
    	self.raise_uncaught_exception(exc)
    
    response.exception = True
    return response
    
    
    
    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:
    	三大认证(认证、权限、频率),用来替换csrf安全认证,要比csrf认证强大得多
    	
    ...
    异常模块  -处理请求异常分支的
    response = self.handle_exception(exc)
    
    二次封装response,处理了结果渲染
    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response
    
    status文件中可以自定义网络状态码
    

    今日日考:

    一、简述一下什么是接口,以及接口文档的编写
    1、接口:采用某种请求方式提交参数,获取响应的响应数据结果的url链接
    	url链接: https://api.*.com/users/
    	请求方式: get
    	请求参数: {...}
    	响应结果: {...}
    	
    2、接口文档:将接口的四部分编写成文档形式(前台后台测试...),YAPI平台编写	
    
    
    二、简述一下接口规范,都需要注意哪些?都是什么含义?
    3、restful接口规范:
    	url链接:https | api | books/(pk) |v1,v2 | ?odering=id
    	请求方式:get查 | post增 |put整体改 | patch局部改 | delete删
    	响应结果:网络状态码与状态信息 | 数据状态吗 | 数据状态信息 | 数据体(子资源返回子资源接口)
    
    4、规范下的接口
    	url('^books/$')=>BookView
    	url('^book/?P<pk>d+/$') =>BookView
    	
    	BookView要实现五个方法,十个逻辑
    	def get(self,request,*args,**kwargs)
    		pk = kwargs.get('pk')
    		if pk:
    		   #单查
    		else:
    		   群查
  • 相关阅读:
    Linux:修改Shell命令提示符及颜色
    Linux:cut命令详解
    pageadmin去掉xxx
    高手详解SQL性能优化十条经验
    一道简单递归题
    list<?>转换成 对应的 class
    《一道笔试题》找出最连续数字的最大长度
    poi 获取excel数据 导入数据库
    有一个5ml 的瓶子 和3ml 的瓶子 和 很多水 现在 要取出4ml的水 请写出编程 多种解法
    假设字符串类似这样的aba和aab,abc和bca就相等,现在随便给你二组字符串,请编程比较他们看是否相等
  • 原文地址:https://www.cnblogs.com/gfhh/p/12093583.html
Copyright © 2011-2022 走看看