zoukankan      html  css  js  c++  java
  • Django中的as_view方法源码分析

    django的类视图拥有自动查找指定方法的功能,通过调用as_views()方法实现。
    在探讨这个问题之前,先引入一段代码举个例子方便理解:
    
    一般请求的判断方法:
    def View(request,*args,**kwargs):
    	if request.method.lower() == 'get':
    		do_something()
    	if request.method.lower() == 'post':
    		do_something()
    
    编写自定义的视图类,前提必须要继承基类View,然后使用View.as_view()代替判断:
    class ClassName(View):
        '''
        继承View自动判断请求方法
        '''
        def post():
            pass
    
        def get():
            pass
    
        def other():
            pass
    
    #调用方法
    url(url, ClassName.as_view(), name)
    
    设计思想:把视图函数的逻辑定义到类的方法里面去,然后在函数中实例化这个类,通过调用类的方法实现函数逻辑。而把逻辑定义在类中的一个好处就是可以通过继承复用这些方法。
    
    那么问题来了,as_view()这个方法是如何执行对应自定义的get或者post方法呢?
    
    as_view
    如果你曾经使用过类视图,那么最熟悉的应该就是这个方法了。要想让类视图生效,必须在 urls.py 的 URL 模式(Pattern)里做类似如下的配置:
    
    # urls.py
    from .views import IndexView  # 导入自定义的视图类
    
    urlpatterns = [
    	url(r^'^$',IndexView.as_view(),name='index')
    ]
    
    Django 使用如上的方式配置 URL 到对应视图函数的路由映射。注意到 url() 函数前两个位置参数需要传递的值,第一个是需要捕获的 url 的正则模式,第二个参数则是一个可调用的对象(即视图函数)。如果我们通过 def 定义视图函数,那么传入的这个可调用对象就是这个函数本身;而如果我们定义的是类视图,则必须调用类视图的 as_view 方法返回一个根据这个类生成的可调用对象。类视图所有的魔法就在这个函数里了,来看看 Django 究竟是如何神奇地把一个类转为一个函数的。
    
       @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:
                    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)
                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.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 方法被调用时允许传递一些关键字参数,不过需要做一个点点检查,第一防止你传入诸如 get、post 这样的关键字参数把类本身的 get、post 方法覆盖了;第二是防止你传入未定义为类属性的参数。最开始的 for 循环就是做这个事。
    
    接下来在 as_view 方法中又定义了一个 view 方法,这个方法相信如果你经常写视图函数的话应该非常眼熟,这就是视图函数的标准定义:接收一个 HttpRequest 对象,以及从 url 捕获的非命名组和命名组参数。只不过在 view 这个视图函数里还多做了一点事,它首先实例化了一个类视图对象,然后把函数的参数设置为了这个类视图实例的属性,接着便调用了实例的 dispatch 方法返回视图函数被要求返回的 HttpResponse 对象(注意 dispatch 方法会根据 HTTP 请求方法的不同去调用对应的处理方法)。接着把类中的一些文档字符串和函数名等更新到定义的 view 函数中,然后 as_view 方法返回这个 view 函数。
    
    调用顺序: as_view --> view --> dispatch
    可以看出as_view实际上是一个闭包,他的作用就是做一些检验工作,再返回view方法
    而view方法的作用是给请求对象补充三个参数,并调用dispatch方法处理
    dispatch方法查找到指定的请求方法,并执行相应代码块
    可以得出结论:as_view方法实际上最后就是要调用dispatch方法
    所以回过头来再看一下我们的 url 模式定义:
    
    urlpatterns = [
    	url(r^'^$',IndexView.as_view(),name='index')
    ]
    
    views.IndexView.as_view() 调用后返回的就是一个在 IndexView 里通过 def 定义的视图函数 view(注意所有类视图都继承自 View 基类),是不是和你直接在这里放一个视图函数是一样的?
    
    附加一张图片加深印象:
    
    
    
    总结
    现在我们已经明白了类视图的基本结构,其主要功能就是根据 HTTP 请求方法的不同做出相应处理,具体的实现为 dispatch 方法。类视图的核心思想就是把视图函数的逻辑定义到类的方法里面去,然后在函数中实例化这个类,通过调用类的方法实现函数逻辑。
    
    
    
  • 相关阅读:
    python 杂谈
    python: list转字符串
    dataframe
    time模块
    python 调试器
    BAT机器学习面试1000题系列(41-45题)
    join()函数
    value_counts()
    模型评估
    04flask_scripts使用
  • 原文地址:https://www.cnblogs.com/ludundun/p/12127475.html
Copyright © 2011-2022 走看看