rest_framework ---APIView

APIView源调用流程

1.首先从django项目跟url开始

我们已get请求publish页面为例,如下先在跟目录找到

r'^publish/'  ---->执行对应的函数  views.PublishView.as_view()

urls.py:

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publish/',views.PublishView.as_view()) ]

查找顺序:views.py----->PublishView------>APIView

文字说明:先查找views.py下的PublishView,看看自定义类是否有as_view方法,没有就开始向父类APIView查找,在APIView中有as_view方法,其实通过32行

     代码我们知道APIView执行的还是它父类View中的as_view方法返回了一个内嵌的view函数,这个函数执行的结果我们可以看到得到的是一个

      self.dispatch(request, *args, **kwargs),这个self很关键,通过 self = cls(**initkwargs),我们知道这个self就是调用这个类方法的一个实例

    谁来调用这个函数self就是谁的实例,所以在我们这个例子中self指代的及时PublishView的实例对线,所以在调用dispatch方法先从自定义的PublishView中找

    ,我们这个class中没有dispatch所以开始找它的父类APIView,在APIView中找到了我们需要的dispatch,所以开始执行这个分发,走到这里我们可以看到

    rest_framework在APIView接口中和CBV的区别就是APIVIew自定义了一个dispatch对CBV的view方法中的dispatch进行了一个拦截,有点类似我们组件中的

    通用父类和自定义配置类

 1 # views.py:
 2 
 3 from rest_framework.views import APIView
 4 
 5 class PublishView(APIView):
 6 
 7     def get(self,request):
 8         pass
 9 
10 
11     def post(self,request):
12         pass
13 
14 # rest_framework/views.py
15 
16 class APIView(View):
17     settings = api_settings
18     schema = DefaultSchema()
19 
20     @classmethod
21     def as_view(cls, **initkwargs):
22         
23         if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
24             def force_evaluation():
25                 raise RuntimeError(
26                     'Do not evaluate the `.queryset` attribute directly, '
27                     'as the result will be cached and reused between requests. '
28                     'Use `.all()` or call `.get_queryset()` instead.'
29                 )
30             cls.queryset._fetch_all = force_evaluation
31 
32         view = super(APIView, cls).as_view(**initkwargs)
33         view.cls = cls
34         view.initkwargs = initkwargs
35 
36         return csrf_exempt(view)
37   
38   
39 def dispatch(self, request, *args, **kwargs):
40     
41     self.args = args
42     self.kwargs = kwargs
43     request = self.initialize_request(request, *args, **kwargs)
44     self.request = request
45     self.headers = self.default_response_headers  # deprecate?
46 
47     try:
48         self.initial(request, *args, **kwargs)
49 
50         # Get the appropriate handler method
51         if request.method.lower() in self.http_method_names:
52             handler = getattr(self, request.method.lower(),
53                               self.http_method_not_allowed)
54         else:
55             handler = self.http_method_not_allowed
56 
57         response = handler(request, *args, **kwargs)
58 
59     except Exception as exc:
60         response = self.handle_exception(exc)
61 
62     self.response = self.finalize_response(request, response, *args, **kwargs)
63     return self.response
class View(object):
   
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    @classonlymethod
    def as_view(cls, **initkwargs):
       
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

 

posted @ 2018-08-02 16:41  似水年华梦  阅读(104)  评论(0编辑  收藏  举报