view.py
from rest_framework.views import View
class Index(View):
def get(self,request,):
pass
def post(self,request):
pass
# 分析:
# 继承View类,会根据请求执行get或者post方法,具体是怎么实现的,我们去urls.py里看
url.py
from django.conf.urls import url
from django.contrib import admin
from apps import views
urlpatterns = [
url(r'index/',views.Index.as_view())
]
# 分析:
# 之前的FBV我们这里的url用的是views.方法名,然后在内部判断用户发来的请求方式执行代码,CBV里我们这里用的是as_view,那一定是在as_view里面做了一些处理
url里执行as_view()方法分析和dispatch方法
@classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.
"""
for key in initkwargs:
if key in cls.http_method_names:
# http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 传来的参数不可用methods里的方法名
raise TypeError(...)
if not hasattr(cls, key):
raise TypeError(.....)
# 分析:
# 首先要判断as_view()里面传进来的参数是否有和http_method_names里的元素相同的,如果有则抛出异常,再判断类里面有没有方法和http_method_names里的元素相同的,如果没有也抛出异常。
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
# 分析:
# 这个view也是as_view()里的方法,self等于当前类的实例化对象,如果对象由get方法但是没head方法,那这时就把get方法赋给head方法,返回dispatch方法。我们再去看看dispatch方法。
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
---------------------------------------------------------
# return的dispatch
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
# http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
# 分析:
# 判断用户请求的method方法是否在http_method_names里,如果在,执行,否则走http_method_not_allowed方法。
def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return http.HttpResponseNotAllowed(self._allowed_methods())