标签:import 做了 row 判断 def ade hook header 解析
安装 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)请求走的是APIView的as_view函数;
2)在APIView的as_view调用父类View的as_view(Django原生的),还禁用了csrf认证
3)在父类的as_view中分发dispatch方法走的又是APIView的dispatch
4)完成任务分发,交给视图类的请求方法处理,得到请求的响应结果,返回给前台
主要关注APIView的dispatch方法。
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
源码入口: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-data和urlencoded,上面三种都能获取到数据。但是当前台提交的是json数据时,只有data能够获得,其他都是空。
总结:
drf对原生request做了二次封装,_request就是原生的request;
原生request对象的属性和方法都可以被drf的_request对象直接访问;
drf请求的所有拼接参数(get请求携带的参数)均被解析到query_params中,所有数据包数据(post请求在请求体中的数据)都被解析到data中
有两种渲染方式:json和browser浏览器。
渲染模块源码入口: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配置中改,具备就在自定义视图类中加类属性。
url拼接参数:只有一种传参方式:拼接参数到url中(在url中)
数据包参数:有3种:form-data、urlencoded和json。
解析模块源码入口: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格式提交的数据。
异常模块源码入口:APIView类的dispatch方法中的response = self.handle_exception(exc)
自定义异常:
比如get取值取不到时,会出现query does not exist异常,显示在前台。
1.在settings.py的REST_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: #默认处理异常时当response为None直接向前台展示,自定义就返回接口 #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)所有经过drf的APIView视图类产生的异常,都可以通过自定义异常提供异常处理方案(比如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.views的exception_handler去做基础处理
2)判断处理的结果(返回值)response,有值代表drf已经处理了,没值就要自己处理。自己处理,可以对exc进行异常判断,然后进行不同的处理。为空二次处理。
(1)响应类构造器
def __init__(self, data=None, status=None, template_name=None, header=None, exception=None, content_type=None): pass
data:响应数据
status:http响应状态码
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={设置的响应头})
标签:import 做了 row 判断 def ade hook header 解析
原文地址:https://www.cnblogs.com/yq055783/p/13149626.html