drf请求生命周期分析

ef as_view(cls, **initkwargs):

 """

 Store the original class on the view function.

 This allows us to discover information about the view when we do URL

 reverse lookups.  Used for breadcrumb generation.

 """

 # 判断 queryset 是否是 QuerySet 对象

 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 = super().as_view(**initkwargs)

 view.cls = cls

 view.initkwargs = initkwargs

 # Note: session based authentication is explicitly CSRF validated,

 # all other authentication is CSRF exempt.

 # 禁用了 csrf 认证

 return csrf_exempt(view)

通过这行代码 view = super().as_view(**initkwargs) ,可以知道 APIView 的 as_view 方法也调用了父类 View 的 as_view 方法,源码如下 :

def as_view(cls, **initkwargs):

 """Main entry point for a request-response process."""

 for key in initkwargs:

     if key in cls.http_method_names:

         raise TypeError("You www.sangpi.comtried 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)

     # 如果有 get 游戏属性,外汇跟单gendan5.com没有 head 属性,那么 head 就是 get

     if hasattr(self, 'get') and not hasattr(self, 'head'):

         self.head = self.get

     # 初始化所有视图方法共享的属性

     self.setup(request, *args, **kwargs)

     # 如果没有 request 属性,报异常

     if not hasattr(self, 'request'):

         raise AttributeError(

             "%s instance has no 'request' attribute. Did you override "

             "setup() and forget to call super()?" % cls.__name__

         )

     # 返回一个 `dispatch` 方法

     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

as_view 方法返回的是 view , view 返回的是 dispatch 方法, dispatch 方法也是调用的 APIView 下的 dispatch 方法,游戏源码如下:

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 对象

 request = self.initialize_request(request, *args, **kwargs)

 self.request = request

 self.headers = self.default_response_headers  # deprecate?

 try:

     # 在调用方法处理程序之前运行任何需要发生的操作

     self.initial(request, *args, **kwargs)

     # Get the appropriate handler method

     # 获取 request 的请求方法

     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
上一篇:CLR、CLI、CTS、CLS的关系


下一篇:2021-06-10