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 方法。类视图的核心思想就是把视图函数的逻辑定义到类的方法里面去,然后在函数中实例化这个类,通过调用类的方法实现函数逻辑。

原文地址:https://www.cnblogs.com/ludundun/p/12127475.html

时间: 2024-08-29 23:31:47

Django中的as_view方法源码分析的相关文章

Django的settings文件部分源码分析

Django的settings文件部分源码分析 在编写Django项目的过程中, 其中一个非常强大的功能就是我们可以在settings文件配置许多选项来完成我们预期的功能, 并且这些配置还必须大写, 否则就不会生效. 此外, Django自身还有一套更详细的配置, 那Django是如何做到用户配置了相关配置就使用用户的配置, 否则就使用自己默认的配置. 带着这样的疑问, 去查看了用户配置项相关的源码部分. 过程分析 首先启动Django项目, 一般Django都是通过python manage.

invalidate和requestLayout方法源码分析

invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewGroup没有重写这些方法),如下: /**  * Mark the area defined by dirty as needing to be drawn. dirty代表需要重新绘制的脏的区域  * If the view is visible, onDraw(Canvas) will be c

关于java中ReentrantLock类的源码分析以及总结与例子

一,官方描述 关于ReentrantLock的官方描述,英文的就不贴出来了,这里我只贴出我自己翻译的描述: reentrant是一个跟synchronized具有相同行为和语义的持有锁来访问方法和语句的互斥锁,但是reentrant还拥有被扩展的能力. ReentrantLock会被线程拥有并且持续锁定,不会解锁.线程调用lock()方法返回后,则成功持有锁,否则这个锁正在被另一个线程所持有,只能等待另一个线程释放锁,如果当前线程拥有了锁,则调用lock()方法会立即返回,这个状态可以通过isH

JDK中String类的源码分析(二)

1.startsWith(String prefix, int toffset)方法 包括startsWith(*),endsWith(*)方法,都是调用上述一个方法 1 public boolean startsWith(String prefix, int toffset) { 2 char ta[] = value; 3 int to = toffset; 4 char pa[] = prefix.value; 5 int po = 0; 6 int pc = prefix.value.l

Netty中NioEventLoopGroup的创建源码分析

NioEventLoopGroup的无参构造: 1 public NioEventLoopGroup() { 2 this(0); 3 } 调用了单参的构造: 1 public NioEventLoopGroup(int nThreads) { 2 this(nThreads, (Executor)null); 3 } 继续看到双参构造: 1 public NioEventLoopGroup(int nThreads, Executor executor) { 2 this(nThreads,

Java split方法源码分析

Java split方法源码分析 1 public String[] split(CharSequence input [, int limit]) { 2 int index = 0; // 指针 3 boolean matchLimited = limit > 0; // 是否限制匹配个数 4 ArrayList<String> matchList = new ArrayList<String>(); // 匹配结果队列 5 Matcher m = matcher(inp

Java中arraylist和linkedlist源码分析与性能比较

Java中arraylist和linkedlist源码分析与性能比较 1,简介 在java开发中比较常用的数据结构是arraylist和linkedlist,本文主要从源码角度分析arraylist和linkedlist的性能. 2,arraylist源码分析 Arraylist底层的数据结构是一个对象数组,有一个size的成员变量标记数组中元素的个数,如下图: * The array buffer into which the elements of the ArrayList are sto

Django——基于类的视图源码分析 二

源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图(RedirectView). View及View的执行顺序 View是所有基于类的视图的基类.仅实现了一些基本的方法和必要的检查工作.其中最重要的是dispatch方法.再次方法中,根据HTTP请求 中的method参数,调用相应的同名处理函数.这里留下了一个口子,后续的类需要根据自己的情况来填补

jQuery实现DOM加载方法源码分析

传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但是onload事件触发过于缓慢,尤其是在存在很多外部图片或者视频文件的时候,为了更好的了解这一点有必要知道一个html文档是如何进行加载的,这里引用一个园友的表述: 1.用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件: 2.浏览器开始载入htm