APIview请求生命周期
APIview的as_view类(局部禁用csrf) ---> 走父级的as_view调用dispatch分发请求 ---> APIview自己重写了dispatch,使用自己完成分发 ---> 分发前完成request二次封装,数据解析 ---> 三大认证 ---> 请求的实际响应 ---> (自己的视图类的处理分发) ---> 出现了异常,就会交给异常模块处理异常 ---> 响应模块完成响应,渲染模块可以json或浏览器两种方式渲染
请求模块
"""
dispatch ---> initialize_request ---> Request
"""
# dispatch中
request = self.initialize_request(request, *args, **kwargs)
# initialize_request返回initial request object
def initialize_request(self, request, *args, **kwargs):
# 返回一个字典
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
# Request类中会将wsgi的request赋值给drf的request对象
self._request = request
@property
def query_params(self):
return self._request.GET
"""
源码分析
print(request._request.method) # 在内部将wsgi的request赋值给request._request
print(request.method) # 就是通过Request类里__getattr__走的是request._request.method
print(request.query_params) # 走的是方法属性,就是给request._request.GET重新命名(property装饰器)
print(request.data) # 走的是方法属性,值依赖于request._full_data(property装饰器)
"""
解析模块
"""
dispatch ---> initialize_request的get_parsers ---> 遍历返回parser_classes并执行 ---> api_settings.DEFAULT_PARSER_CLASSES
"""
REST_FRAMEWORK = {
# 全局配置解析类:适用于所有视图类
'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: 响应的网络状态码
-------------------
template_name: drf完成前后台不分离返回页面,但是就不返回data(了解)
headers: 响应头,一般不规定,默认(了解)
exception: 一般异常响应,会将其设置成True,默认False(了解)
content_type: 默认就是 application/json, 不需要处理
"""
渲染模块
"""
局部配置:renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
全局配置:
RESR_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer', # 上线后尽量关闭
]
}
"""
异常模块
"""
dispatch ---> handle_exception --->
"""
def handle_exception(self, exc):
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()
# 执行views.py中的exception_handler方法
response = exceptio n_handler(exc, context)
if response is None:
self.raise_uncaught_exception(exc)
response.exception = True
return response
二次封装exception_handler方法
# 一定要在settings文件中将异常模块配置自己的异常处理函数
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
def exception_handler():
response = drf_exception_handler(exc, context)
detail = %s + %s + %s % (context.get('view'), context.get('request').method, exc)
if not response:
# 原生exception_handler不会再返回None了
response = Response({'detail': detail})
else:
response.data = {'detail': detail}
# 核心: 要将request.data.get('detail')信息记录到日志文件
# logger.waring(response.data.get('detail'))
return response