摘要
写完实例化后,我们会写主视图。drf中,我们通常使用类视图,最基本的是APIView。这一章详细介绍drf的要求生命周期。
正文
Django(47)drf要求生命期剖析
序言
一般大家写完实例化之后,大家便会逐渐写主视图了,drf
中大家一般应用CBV
的方法,也就是类主视图的方法,最基本的大家会应用from rest_framework.views import APIView
,APIView
承继自View
,有关主视图的详细说明,大家事后再细讲。此章详细介绍drf
的要求生命期
外置准备工作
大家先写一个主视图类TestView
,编码以下:
from rest_framework.views import APIView
from rest_framework.response import Response
class TestView(APIView):
def get(self, request, *args, **kwargs):
return Response("drf get ok")
def post(self, request, *args, **kwargs):
return Response("drf post ok")
留意:这儿的Response
务必是drf下的Response
,不可以是Django原生态的HttpResponse
或是是JsonResponse
,不然会错误
然后,在urls.py
中配备路由器,以下
urlpatterns = [
path('test/', views.TestView.as_view(), name="Test"),
]
随后大家浏览http://127.0.0.1:8000/drf/test/
,会发生下面的图款式,意味着要求取得成功
然后我们在插口专用工具中应用POST
要求方法浏览,回到結果以下:
"drf post ok"
之上2种浏览方法都成功了,下面大家剖析在其中的要求全过程及其基本原理
要求生命期剖析
最先大家先从路由器配备中见到views.TestView.as_view()
,启用的是TestView
类主视图下的as_view
方式,可是大家上边界定该方式的情况下,沒有调用as_view()方式
,因此会启用父类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.
"""
# 分辨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 tried 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特性,沒有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
dispatch
回到一个response
回应目标,获得要求的回应結果,回到给前台接待
汇总
- url要求走的是
APIView
的as_view
涵数 - 在
APIView
的as_view
启用父类(django原生态)的as_view
,还禁止使用了csrf
验证 - 在父类的
as_view
中的dispatch
方式要求走的也是APIView
的dispatch
- 达到目标方式交到主视图类涵数解决,获得要求的回应結果,回到给前台接待
关注不迷路
扫码下方二维码,关注宇凡盒子公众号,免费获取最新技术内幕!
评论0