百木园-与人分享,
就是让自己快乐。

django中CBV视图模式的View源码分析

位置:

1.找到自己项目用的解释器存储位置
H:\\pythonProject\\Lib\\site-packages\\django\\views\\generic\\base.py
在base.py里有一个View类

2.也可以通过from django.views import View 按住ctrl点击View会直接跳到该类的位置

CBV形式的路由

path(r\'^login/\',views.MyLogin.as_view())

CBV形式的视图函数

from django.views import View
class MyLogin(View):
def get(self,request): #get请求时执行的函数
	return render(request,\'form.html\')
def post(self,request):  #post请求时执行的函数
	return HttpResponse(\'post方法\')

CBV源码分析:

当上述的login请求来了之后---》会执行后面的views.MyLogin.as_view()---》这个地方应该放的是函数的内存地址,views.MyLogin.as_view()执行完,是个函数内存地址,---views.MyLogin.as_view()会去views.py中找到MyLogin这个类,然后找as_view()方法,发现没有--》去其父类中找就是View类中找---》执行as_view()方法最终返回的是一个View类内部的一个view函数内存地址---》然后django框架会自动给view这个函数加括号调用,再传入request这个参数--->而view这个内部函数返回的是return handler(request, *args, **kwargs)就是对应类中get或者post方法

as_view()方法分析:

@classonlymethod # 1.这个as_view是一个类方法,所以用类调用时,会自动把调用的类传入给这个函数的cls
def as_view(cls, **initkwargs):
    \"\"\"Main entry point for a request-response process.\"\"\"
    # 2.因为url那边没有传参,所以initkwargs为空,先忽略该层代码
    for key in initkwargs:
        if key in cls.http_method_names:
            raise TypeError(
                \"The method name %s is not accepted as a keyword argument \"
                \"to %s().\" % (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)
            )

    # 3.执行该view函数
    def view(request, *args, **kwargs): # request是当次请求的数据
        # 5.cls是当前调用的类MyLogin,cls加括号产生对象给了self,这里现在self就是类MyLogin产生的对象
        self = cls(**initkwargs)
        self.setup(request, *args, **kwargs)
        if not hasattr(self, \"request\"):
            raise AttributeError(
                \"%s instance has no \'request\' attribute. Did you override \"
                \"setup() and forget to call super()?\" % cls.__name__
            )
        # 6.view函数返回了self.dispatch(request, *args, **kwargs)方法,
        # self本身没有dispatch方法,就去MyLogin中找,MyLogin没有就去View类中找,找到了
        return self.dispatch(request, *args, **kwargs)

    view.view_class = cls
    view.view_initkwargs = initkwargs

    # __name__ and __qualname__ are intentionally left unchanged as
    # view_class should be used to robustly determine the name of the view
    # instead.
    view.__doc__ = cls.__doc__
    view.__module__ = cls.__module__
    view.__annotations__ = cls.dispatch.__annotations__
    # Copy possible attributes set by decorators, e.g. @csrf_exempt, from
    # the dispatch method.
    view.__dict__.update(cls.dispatch.__dict__)

    # Mark the callback if the view class is async.
    if cls.view_is_async:
        view._is_coroutine = asyncio.coroutines._is_coroutine

    # 4.as_view返回的是该函数内部的view函数内存地址,所以具体读下view函数就行
    return view

上述as_view()方法返回了一个dispatch方法,dispatch方法分析:

# 1.dispatch将MyLogin这个类产生的对象self和request请求对象传入了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.
    # 2.判断request.method方法在不在http_method_names里,ttp_method_names对象里没有最后去View类里找到了
    if request.method.lower() in self.http_method_names:
        # 3.通过getattr方法反射,self.http_method_not_allowed这个就当没有前面的方法时的一个默认值
        # handler最后得到的就是MyLogin中定义的get或者post方法的内存地址
        handler = getattr(
            self, request.method.lower(), self.http_method_not_allowed
        )
    else:
        handler = self.http_method_not_allowed
    # 4.最后这个方法将handler加括号,再传入request参数调用的结果返回出去==执行了MyLogin的get或者post方法
    return handler(request, *args, **kwargs)

来源:https://www.cnblogs.com/suncolor/p/16819758.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » django中CBV视图模式的View源码分析

相关推荐

  • 暂无文章