1. 程式人生 > 其它 >drf請求生命週期分析

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