drf 内部模块
drf配置与注册
原生Django与drf比较
APIView的请求生命周期
1)APIView类继承View类,重写了as_view和dispatch方法
2)重写的as_view方法,主体还是View的as_view,只是在返回视图view函数地址时,局部禁用csrf认证
3)重写的dispatch方法,
在执行请求逻辑前:请求模块(二次封装request)、解析模块(三种数据包格式的数据解析)
在执行请求逻辑中:进行三大认证(认证,权限,频率),用来替换csrf安全认证;异常模块(执行出现任何异常交给异常模块处理)
在执行请求逻辑后:响应模块(二次封装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
解析模块
解析模块:只处理数据包参数 - form-data,urlencoded,json
1)全局配置所有视图类的解析方式,解析配置可以配置三种
2)局部配置当前视图类的解析方式,解析配置可以配置三种
3)配置的查找顺序:局部(视图类的类属性) => 全局(settings文件的drf配置) => 默认(drf的默认配置)
注:该模块了解,但是全局局部配置是重点
源码分析:
入口:APIVIew的dispatch方法的 request=self.initialize_request(request, *args, **kwargs)
获取解析类:parsers=self.get_parsers(),
进行局部全局默认配置查找顺序进行查找:return [parser() for parser in self.parser_classes]
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
局部配置:parser_classes = [JSONParser, FormParser, MultiPartParser]
全局配置:
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
响应模块
Respose(data=常量|列表|字典, status=网络状态码)
data:响应数据
status:响应的网络状态码
-------------------------
template_name:drf完成前后台不分离返回页面,但是就不可以返回data(不许用了解)
headers:响应头,一般不规定,走默认
exception:一般异常响应,会将其设置成True,默认False(不设置也没事)
content_type:默认就是 application/json,不需要处理
from rest_framework import status class BookAPIView(APIView): def get(self, request, *args, **kwargs): response = Response( data={ 'msg': 'apiview get ok' }, status=status.HTTP_404_NOT_FOUND, ) print(response.data) return response
渲染模块
Postman请求结果是json,浏览器请求结果是页面
可以全局与局部配置
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
局部配置:renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
全局配置:
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', # 上线后尽量关闭
],
异常模块
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 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
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.parsers import JSONParser, FormParser, MultiPartParser from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer from rest_framework import status class BookAPIView(APIView): # 局部配置解析类:只适用当前视图类 parser_classes = [JSONParser, FormParser, MultiPartParser] # 局部配置渲染类:只适用当前视图类 renderer_classes = [JSONRenderer, BrowsableAPIRenderer] def get(self, request, *args, **kwargs): # a response = Response( data={ 'msg': 'apiview get ok' }, status=status.HTTP_404_NOT_FOUND, ) print(response.data) return response 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' })