drf之模块

Posted yq055783

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drf之模块相关的知识,希望对你有一定的参考价值。

1.介绍

安装 pip install djangorestframework

注册:在INSTALLED_APPS列表中写:”rest_framework”

drf框架的封装风格:

import rest_framework
from rest_framework.views import View                    #视图
from rest_framework.response import Response    #响应
from rest_framework.request import Request    #请求
from rest_framework.serializers import Serializer    #序列化器
from rest_framework.settings import APISettings    #设置
from rest_framework.filters import SearchFilter    #过滤器
from rest_framework.pagination import PageNumberPagination #分页
from rest_framework.authentication import TokenAuthentication    #登陆
from rest_framework.permissions import IsAuthenticated    #权限
from rest_framework.throttling import SimpleRateThrottle    #频率

 

drf请求生命周期:

1)请求走的是APIViewas_view函数

2)APIViewas_view调用父类Viewas_viewDjango原生的),还禁用了csrf认证

3)在父类的as_view中分发dispatch方法走的又是APIViewdispatch

4)完成任务分发,交给视图类的请求方法处理,得到请求的响应结果,返回给前台

主要关注APIViewdispatch方法。

dispatch源码分析:

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
        #请求模块(解析模块)
        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

 

2.请求模块:request对象

源码入口:APIView类的dispatch方法中:request = self.initialize_request(request, *args, **kwargs)

 

get请求的数据(拼接的参数)可以通过三个方法得到:

request._request.GET        #二次封装

request.GET #兼容

request.query_params   #用这个   扩展

 

post请求的数据(数据包)

request._request.POST     

request.POST

request.data     #通过data拿数据,三种数据方式都能拿

对于form-dataurlencoded,上面三种都能获取到数据。但是当前台提交的是json数据时,只有data能够获得,其他都是空。

 

总结:

drf对原生request做了二次封装,_request就是原生的request

原生request对象的属性和方法都可以被drf_request对象直接访问;

drf请求的所有拼接参数(get请求携带的参数)均被解析到query_params中,所有数据包数据(post请求在请求体中的数据)都被解析到data

3.渲染模块

有两种渲染方式:jsonbrowser浏览器。

渲染模块源码入口:APIView类的dispatch方法中:self.response = self.finalize_response(request, response, *args, **kwargs)

全局配置:

settings.py配置文件中配置REST_FRAMEWORK,就全局配置所有接口的渲染方式(两种:方式1:就只是返回json字符串(比如通过postman),方式2:浏览器方式的数据:有响应信息和json数据)

局部配置:

自定义类中定义类属性(就不去父类中找了)

from rest_framework.renderers import JSONRenderer

render_classes = [JSONRenderer]   #必须是列表,因为要迭代

模板渲染配置走的过程:自定义视图类--->继承APIView视图类--->自定义drf配置---->drf默认配置。

全局配置就在自定义drf配置中改,具备就在自定义视图类中加类属性。

 

4.解析模块

url拼接参数:只有一种传参方式:拼接参数到url中(在url中)

数据包参数:有3种:form-dataurlencodedjson

解析模块源码入口:APIView类的dispatch方法中的 request = self.initialize_request(request, *args, **kwargs)

解析配置也有两种:

全局解析类、局部解析类

全局配置:

settings.py中的REST_FRAMEWORK字典中,写入

DEFAULT_PARSER_CLASSES: [
        rest_framework.parsers.JSONParser,
        rest_framework.parsers.FormParser,
        rest_framework.parsers.MultiPartParser
    ],      #三个都写上,那么3个都支持

局部配置:

在自定义类中写

from rest_framework.parsers import JSONParser
parser_classes = [JSONParser]    #写了这个这个类就只支持解析json格式提交的数据。

 

5.异常处理模块

异常模块源码入口:APIView类的dispatch方法中的response = self.handle_exception(exc)

自定义异常:

比如get取值取不到时,会出现query does not exist异常,显示在前台。

1.settings.pyREST_FRAMEWORK字典中全局配置异常模块

“EXECPTION_HANDLER” :”api.exception.exception_handler”

get_exception_handler从默认的异常处理变为自己定义的异常处理函数

自定义异常就是提供exception_handler异常处理函数,处理的目的就是让response一定有值。

 

2.在应用下api新建一exceptions.py文件

from rest_framework.views import exception_handler as drf_exception_handler

form rest_framework.views import Response

def exception_handler(exc, context):

response = drf_exception_handler(exc, context)   #先交给默认的exception_handler处理

if response is None:    #默认处理异常时当responseNone直接向前台展示,自定义就返回接口

    #if isinstance(exc, ‘’)   可以对exc的不同类型做判断,返回不同的异常

return Response({

“detail”: “服务器错误”

})

return response

 

 

源码逻辑分析:

首先源码入口为APIView类的dispatch方法中的response = self.handle_exception(exc)

handle_exception里然后执行exception_handler = self.get_exception_handler(),从exception_handler 中获取response,如果response有值,就返回,没有值就报错给前台。get_exception_handler是从settings中获取exception_handler函数。exception_handler是处理异常的逻辑,要么返回response,要么返回None。可以在自定义exception_handler函数,然后再配置中指定自定义的异常函数,这样就会走自定义的。同时为了复用默认的异常处理,可以在自定义异常函数中先导入默认的,生成response,再针对response处理(比如是None,返回具体的错误)。

 

总结:

为什么要自定义异常模块?

1)所有经过drfAPIView视图类产生的异常,都可以通过自定义异常提供异常处理方案(比如get默认就没有处理异常,就会在前台显示错误的细节)。

2)drf默认提供了异常处理方案(在rest_framework.views.exception_handler中),单处理范围有限

3)drf提供的处理方案有两种:处理了就返回处理信息,没处理就返回None(后续就是服务器抛异常给前台)。

4)自定义异常的目的就是解决drf没有处理的异常,让前台得到合理的异常信息,后台记录异常具体信息。

 

处理方案:

 修改配置文件

REST_FRAMEWORK = {
 “EXECPTION_HANDLER” :”api.exception.exception_handler”
 }

自定义exception_handler函数。

1)先将异常处理交给rest_framework.viewsexception_handler做基础处理

2)判断处理的结果(返回值)response,有值代表drf已经处理了,没值就要自己处理。自己处理,可以对exc进行异常判断,然后进行不同的处理。为空二次处理

 

6.响应模块

1)响应类构造器

def __init__(self, data=None, status=None,
            template_name=None, header=None,
            exception=None, content_type=None):
        pass        

data:响应数据

statushttp响应状态码

content_type:继承父类,默认是json,不用设置。

其他不用了解。

直接在自定义异常返回的Response中带上有名实参。

return Response({
    “detail”: “服务器错误”
}, status=500, exception=True)

这个500可以从定义的变量中导入:from rest_framework import status

status=status.HTTP_500_INTERNAL_SERVER_ERROR

 常规实例化响应对象:

return Response(data={数据}, status=XXX, headers={设置的响应头})

 

以上是关于drf之模块的主要内容,如果未能解决你的问题,请参考以下文章

DjangoDRF源码分析之五大模块

DRF框架之视图的扩展类简介

drf之jwt傻瓜式启动说明书

DjangoDRF源码分析之三大认证

DRF之APIView源码解析

DRF框架serializer之视图优化