一、APIView请求生命周期
1、APIView类继承View类,重写了as_view和dispatch方法;
2、重写的as_view方法,主题还是View的as_view,只是在返回视图view函数地址时,局部禁用csrf认证
3、重写的dispatch方法:
? 在执行请求逻辑前:请求模块(二次封装request)、解析模块(三种数据包格式的数据解析);
? 在执行请求逻辑中:异常模块(执行出现任何异常交个异常模块处理)
? 在执行请求逻辑后:响应模块(二次封装response)、渲染模块(响应的数据能JSON和页面两种渲染);
二、请求模块
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
三、解析模块
1、全局配置所有视图类的解析方式,解析配置可以配置三种;
2、局部配置当前视图类的解析方式,解析配置可以配置三种;
3、配置低的查找顺序:局部(视图类的类属性)=>全局(setting文件的drf配置)=>默认(drf的默认配置);
注:全局局部配置是重点。
局部:
全局:
#源码解析:
#入口:APIView的dispatch方法的request=self.instialize_request(request,*args,**kwargs)
#获取解析类:parsers = self.get_parsers(),
#进行局部-全局-默认配置查找顺序进行查找:
return [parser() for parser in self.parser_classes]
#局部配置(在视图类中配置):
parser_classes = [JSONParser, FormParser, MultiPartParser]
#全局配置(在setting中配置):
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
四、响应模块
‘data‘:响应数据(熟悉)
‘status‘:响应的网络状态码(熟悉)
template_name:drf完成前后台不分离返回页面,但是就不可以返回data(不需要掌握)
headers:响应头,一般不规定,走默认
exception:一般异常响应,会将其设置成True,默认False(不设置也没事)
content_type:默认就是application/json不需要处理
五、渲染模块(了解)
Postman软件测试请求结果是json,浏览器请求结果是页面
局部:
全局:
#局部配置渲染类(在视图类中配置):只适用当前视图类
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
#全局配置渲染类:适用于所有视图类
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer', # 上线后尽量关闭
],
六、异常模块
1、所有经过drf的AIPView视图类产生的异常,都可以提供异常处理方案(包括三大认证);
2、drf默认提供了异常处理方案(rest_framework.views.exception_handler),但是
处理范围有限;
3、drf提供的处理方案两种,处理后的异常(一般都是前端出现的错误)返回异常现象,没有处理(一般都是服务器错误)返回None;
4、自定义异常的目的就是解决drf没有处理的异常,让前台得到合理的异常信息返回,后台记录异常的具体信息;
ps:ORM查询时的错误drf一般不自动处理.
'''
#异常模块:APIView类的dispatch方法中
request=self.handle_exception(exc)#点进去
#获取处理异常的句柄(方法)
#一层层看源码,走的是配置文件,拿到的是rest_framework.views的exception_handler
#自定义:直接写exceptiot_handler函数,在自己的配置文件配置EXCEPTION_HANDLER指向自己写的
exception_handler = self.get_exception_handler()
#异常处理的结果
#自定义异常就是提供exception_handler异常处理函数,处理的目的就是让response一定有值
response= exception_handler(exc,context)
'''
# 一定要在settings文件中将异常模块配置自己的异常处理函数
#settings中配置:
REST_FRAMEWORK = {
# 全局配置异常模块
'EXCEPTION_HANDLER': 'api.exception.exception_handler', # api为应用名
}
#自定义异常处理py文件
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
# 先交个drf处理客户端异常,如果结果response为None代表服务器异常,自己处理
# 最终一定要在日志文件中记录异常现象
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('detail')信息记录到日志文件
# logger.waring(response.data.get('detail'))
return response