django Rest Framework----APIView 执行流程 APIView 源码分析

django—CBV源码分析中,咱们是分析的from django.views import View下的执行流程,这篇博客咱们介绍django Rest Framework下的APIView的源码分析。html

1、as_view()

咱们仍是先从URLconfig中入手,因为BookView是一个基于类的视图,因此咱们将URL指向as_view()类方法django

url(r'books/',views.BookView.as_view()),

此时,咱们的BookView已经不是继承自django.views中View了,而是restframework.views中的APIView函数

安装Django RestFramework源码分析

pip install djangorestframework

BookView视图类post

from django.shortcuts import render,HttpResponse #导入APIView
from rest_framework.views import APIView #继承自APIView
class BookView(APIView): def get(self,request): return HttpResponse('get....') def post(self,request): return HttpResponse('post....')

as_view():因为BookView没有实现as_view()方法,django启动时,调用的as_view()是APIView中的as_view()url

@classmethod def as_view(cls, **initkwargs): """ 将原始类存储在视图函数上 这容许咱们在执行url反向查找时发现有关视图的信息。 """ ... #因为APIView是继承自django.views中的View(上篇博客接触过)
    #调用父类(View)中的as_view()
    view = super(APIView, cls).as_view(**initkwargs) view.cls = cls view.initkwargs = initkwargs # 提示: 基于会话的身份验证被明确地CSRF验证
    # 全部其余身份验证都免予使用CSRF。
    # 跳过CSRF验证
    return csrf_exempt(view)

在APIView中的as_view()方法什么都没作,只是调用了父类的as_view()方法spa

以前的博客介绍过,as_view()方法会返回self.dispatch() ,因为BookView没有实现这个方法,因此咱们查看APIView中dispatch()都作了哪些工做rest

dispatch():和Djnago.views中View类的dispatch()派遣相同,额外添加了一些功能code

# Note: 在“派遣”须要被改写的状况下,能够在"as_view"范围内对CSRF进行豁免,以防止意外移除这一豁免。
def dispatch(self, request, *args, **kwargs): """ 和django.views中View的dispatch()调度差很少, 可是有额外的钩子用于启动、终结和异常处理。 """ self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers  # deprecate?
    try: self.initial(request, *args, **kwargs) # 获取适当的程序处理方法,这里的调度和django View的调度同样
        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 # 调用HTTP请求处理方法,并返回
        response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response

APIView中的dispatch()和Django中的dispatch()相似,不一样之处,APIView对request请求对象进行了从新封装csrf

request:APIView对request对象进行了从新封装

def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers  # deprecate?
 ....

默认的是django.core.handlers.wsgi.WSGIRequest对象,经过调用initialize_request()将其封装成rest_framework.request.Request。经过type(request)来查看

initialize_request():作了哪些工做

def initialize_request(self, request, *args, **kwargs): parser_context = self.get_parser_context(request) # 返回了一个reuqest请求对象
    return Request( request, parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context )

Request类: 完善request请求的一些注意事项,例如用户登陆、检测权限等等

class Request(object): def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): ... #将原始的WSGIReqeust对象复制给_request
        self._request = request .... #调用旧的request.GET
 @property def query_params(self):return self._request.GET #调用旧的request.POST
 @property def POST(self):return QueryDict('', encoding=self._request._encoding)

以后使用的request,都是restfromwork封装的Reqeust对象。

相关文章
相关标签/搜索