drf請求生命週期分析
阿新 • • 發佈:2021-06-11
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