as_view方法源码分析

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())

继承API之后的as_view发生了什么变化:https://blog.nowcoder.net/n/f57a606fc9f244a782d37ccce8eceaef

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务