django中APIView里的dispatch和as_view方法分析
位置:
from rest_framework.views import APIView
继承APIView类视图形式的路由:
path("booksapiview/", views.BooksAPIView.as_view()), #在这个地方应该写个函数内存地址
继承APIView类的视图函数:
from rest_framework.views import APIView
class BooksAPIView(APIView):
def get(self):
pass
def post(self):
pass
APIView源码分析:
继承了APIView的视图函数,最终执行的是APIView里的as_view方法
@classmethod
def 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.
"""
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
# 1.调用APIView父类,也就是View类中的as_view方法,将其返回值view在赋值给view
view = super().as_view(**initkwargs)
# 2.这里践行了一切皆对象的原则,将cls这个视图类给了view.cls,下面哪个也是一样
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
# 3.这句话的意思就是以后所有继承APIView的试图函数都没有csrf认证了,和View类一样,APIview类的as_view方法最后也返回了view
# 只不过apiview新增了去除csrf认证这里
return csrf_exempt(view)
注意:上述返回的view内存地址,需要去找dispatch方法是先去apiview里找,而不是view类中的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是self.initialize_request这个方法返回的新的由rest_framework中的Request类实例化产生的request对象
request = self.initialize_request(request, *args, **kwargs)
# 又把新的request对象给了视图函数中的request,从此,视图函数中的request就是新的request对象了
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 这里执行了apiview里的initial方法,这个方法里面包含了三大认证模块(重要)
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
# 三大认证过了之后,继续走,这里和view里面差不多,通过反射得到对应请求方式的函数地址
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
# 将get请求或者其他请求方式执行之后的结果在给response模块
response = handler(request, *args, **kwargs)
# 这里是三大认证出异常的异常模块
except Exception as exc:
response = self.handle_exception(exc)
# 渲染模块,对response这个相应结果在进行包装(就是在前端看到的由rest_framework渲染出来的数据结果页面)
self.response = self.finalize_response(request, response, *args, **kwargs)
# 返回该渲染模块
return self.response
def initial(self, request, *args, **kwargs):
# 该方法最重要的就是下面三句代码
# Ensure that the incoming request is permitted
# 这个是认证组件
self.perform_authentication(request)
# 这个是权限组件
self.check_permissions(request)
# 这个是频率组件
self.check_throttles(request)