drf框架中的请求组件

02-01 请求组件

1.Django-CBV源码分析

# 视图层:api.views.py
from django.view import View

class BookView(View):
    def get(self, request): pass
    def post(self, request): pass
# 路由层:api.urls.py
from django.conf.urls import url
from api import views

urlpatterns = [
    url(r'^book/$', views.BookView.as_view()),
]
"""
CBV生命周期:
1.项目启动之后,as_view()方法被执行,返回一个view方法的内存地址
2.路由匹配成功后会调用view方法
3.view方法内部将初始化变量(此时将cls(BookView)赋值给self),并调用View的dispatch方法
3.dispatch方法获取请求的方式,判断其是否在8大基本请求方式里面,然后通过反射机制调用self(自定义类BookView)中的对应请求方法
"""

2.Drf的请求组件

2.1 Drf请求组件的使用

# 视图层:api.views.py
from rest_framework.view import APIView
from rest_framework.response import Response

class BookAPIView(APIView):
    def get(self, request, *args, **kwargs):
        # 此时request不是wsgi的request,而是drf在其基础上再次封装的自身的reuqest
        print(request._requst) # request._request 才是wsgi的reuqest
        print(request.query_params.dict())
    def post(self, request, *args, **kwargs): pass
# 路由层:api.urls.py
from django.conf.urls import url
from api import views

urlpatterns = [
    url(r'^books/$', views.BookAPIView.as_view()),
    url(r'^books/(?P<pk>\d+)/', views.BookAPIView.as_view()),
]

2.2 drf请求组件的优点

  1. drf的request是在wsgi的request的基础上再次封装的request,wsgi的request作为drf的request的一个属性:_request
  2. 新的request对旧的request做了完全兼容(新request.GET能够直接获取旧request.GET的内容)
  3. 新的reuqest对数据解析更加规范:所有的拼接参数都解析到query_params中,所有的数据包数据都被解析到data中(query_params和data属于QueryDict类型,可以.dict()转化成原生的dict)
  4. 局部禁用了csrf认证,也就意味着所有继承drf的基本视图类都不再做csrf认证

2.3 drf请求组件源码分析

1.重写as_view()方法,局部禁用csrf认证:

# APIView类的as_view()方法的核心源码
@classmethod
def as_view(cls, **initkwargs):
	# 调用父类(view)的as_view方法
    view = super().as_view(**initkwargs)
    view.cls = cls
    view.initkwargs = initkwargs
	# 禁用csrf认证
    return csrf_exempt(view)

2.重写dispatch()方法,二次封装request:

# APIView类的dispatch()方法的核心源码
def dispatch(self, request, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs
    # 调用initialize_request方法二次封装reqeust
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?
    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response
# APIView类的initiaalize_reqeust()方法的核心源码
def initialize_request(self, request, *args, **kwargs):
    parser_context = self.get_parser_context(request)
	# 返回一个Request对象,也就意味着调用Request的__init__方法
    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )
# request.py下的Request类的核心源码
class Request:
    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        # 讲wsgi的reuqest封装为drf的request中的_request属性
        self._request = request
        self.parsers = parsers or ()
     	...
        self._stream = Empty

3.通过Request类的__getattr__()方法兼容wsgi的request

# request.py下的Request类的核心源码
def __getattr__(self, attr):
    try:
        # 通过反射获取wsgi的request中的attr,如果获取不到再去获取自身的attr
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)
posted @ 2019-11-19 19:45  17vv  阅读(173)  评论(0编辑  收藏  举报