drf 渲染模块
一、drf按照与使用
-
安装drf:
pip3 install djangorestframework
-
settings.py注册app:
INSTALLED_APPS = [ ... 'rest_framework' ]
-
基于cbv完成满足restful规范的接口
# 视图层 from rest_framework.views import APIView from rest_framework.response import Response # CBV接口 class Test(APIView): def get(self,request,*args,**kwargs): print(request.GET) print(request.META) return Response({ 'status': 0, 'msg': 'get ok' }) def post(self,request,*args,**kwargs): print(request.POST) return Response({ 'status': 0, 'msg': 'post ok', })
# 路由层 urlpatterns = [ url(r'^api/', views.Test.as_view()), ]
二、drf CBV源码分析
- 首先在路由层中注册CBV,通过as_view()方法实现CBV,这个和django实现CBV的方法一致。但是drf在CBV中进行了一些其他处理。比如,虽然还是调用的父类的as_view来得到view,但返回时局部禁用了csrf认证
csrf_exempt(view)
- 当请求来的时候,路由视图函数映射关系匹配成功时就会进入请求分发的
dispatch()
方法. - 在
dispatch()
方法内在分发执行视图方法前,完成了:- 二次封装request:self.initialize_request(request, *args, **kwargs)
- 三大认证:self.initial(request, *args, **kwargs)
- 在视图方法处理完请求后:
- 出现异常的处理:self.handle_exception(exc)
- 二次封装response:self.finalize_response(request, response, *args, **kwargs)
'''rest_framework/views.py -> class APIView(view):中'''
@classmethod
def as_view(cls, **initkwargs):
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
# 调用父类as_view方法返回view对象
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
return csrf_exempt(view)
'''rest_framework/views.py -> class APIView(view):中'''
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 二次封装request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 三大认证
self.initial(request, *args, **kwargs)
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)
# 二次封装response
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
注意:接下来大部分关于drf的源码都会从dispatch方法为起点开始分析
三、请求模块源码分析
-
drf的APIView类:重写了as_view(),但主体逻辑还是调用父类View的as_view(),局部禁用了csrf认证
重点:所有继承drf的基本视图类APIView的视图类,都不在做csrf认证校验
-
drf的APIView类:重写了dispatch(),在内部对request进行了二次封装
# 二次封装request request = self.initialize_request(request, *args, **kwargs)
-
initialize_request方法内部源码分析
- 返回了Request类的实例化对象。
- Request类中的
__init__
方法中将原来的request
放到了self._request
中 - 所有的拼接参数都解析到query_params中,所有数据包数据都被解析到data中,通过
@property
装饰器将方法属性包装成数据属性。 - query_params和data属于QueryDict类型,可以通过 .dict() 转化成原生dict类型
-
Request类内部实现了 .拦截方法
__getattr__
来取值,可以直接取到_request中的内容
# CBV接口
class Test(APIView):
def get(self,request,*args,**kwargs):
print(request._request.GET) # 直接找原来的request
print(request.GET) # 通过内部的getattr来找
print(request.META) # 通过内部的getattr来找
# QueryDict转化为原生dict
print(request.query_params.dict())
# 数据包数据
print(request.data)
return Response({
'status': 0,
'msg': 'get ok'
})
def post(self,request,*args,**kwargs):
# 通过内部的getattr来找
print(request.POST)
# QueryDict转化为原生dict
print(request.query_params.dict())
print(request.data.dict())
return Response({
'status': 0,
'msg': 'post ok',
})