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