zoukankan      html  css  js  c++  java
  • CBV之Django中View类部分源码分析

    CBV—基于类的视图

    CBV基本写法:

    views.py中的写法:

    from django.conf.urls import url
    from django.contrib import admin
    from django.views import View
    
    class MyLogin(View):  # 这里的MyLogin是我们自定义的CBV类
        def get(self, request):
            return render(request, 'login.html')
        def post(self, request):
            return HttpResponse('我是类里面的post方法')
    

    url写法:

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

    login.html中的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <form action="" method="post">
        {% csrf_token %}
        <input type="submit">
    </form>
    </body>
    </html>
    

    启动项目,使用浏览器请求url: 127.0.0.1:8000/login/,显示结果为(此时为GET请求)

    当点击提交按钮后,由login.html代码中可见form表单使用的是POST请求,获得如下结果:

    请求达到django会先执行django中间件里的方法,然后执行路由匹配。

    在路由匹配完成后,会执行CBV类中的as_view方法。

    但是此时,我们定义的类中并没有as_view方法,所以会接着到它的父类View中寻找并使用父类中的as_view方法。

    django中View类的部分源码:

    class View(object):
        http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    
        def __init__(self, **kwargs):
            for key, value in six.iteritems(kwargs):
                setattr(self, key, value)
    
        @classonlymethod
        def as_view(cls, **initkwargs):  # cls是我们自己写到的MyLogin类 
            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)  # cls是我们自己写到的MyLogin类
                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
     
            update_wrapper(view, cls, updated=())
    
    
            update_wrapper(view, cls.dispatch, assigned=())
            return view
    
        def dispatch(self, request, *args, **kwargs):
            if request.method.lower() in self.http_method_names:
                # handler = getattr(我们自己写的类产生的对象,'get',报错信息
                # handler就是我们自己类里面的get方法
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
          	# 调用类里面的get方法
    
    
    

    从view中的源码可以看出,再View类中,先定义了http请求的八种方法

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    

    在【as_view】方法中进行判断,如果请求的方法没在 【http_method_names】中,则会抛出异常,

    @classonlymethod
        def as_view(cls, **initkwargs):  # cls是我们自己写到的MyLogin类 
    

    【as_view】方法中又定义了view方法,在view方法中对CBV类进行实例化,并为其设置属性,向浏览器发送request请求。

    最后调用【dispatch】方法并返回【dispatch】方法的值来对request进行处理:

    由于self对象就是CBV实例化得到,所以会先执行自定义的CBV类中的dispatch方法。如果CBV类中没有定义dispatch方法则执行Django的View中的dispatch方法
    
  • 相关阅读:
    c++ 面试注意的问题
    非root用户 gcc安装
    爱挑剔的acm程序员 acmer
    Add Digits
    Rectangle Area
    Contains Duplicate III 下标范围<=k 值范围<=t
    ruby第一次实践 ”hello world“
    判断一个 int 向量里是否有相同的数 并且距离在k之内 (2)
    判断一个 int 向量里是否有相同的数(1)
    字符串同构
  • 原文地址:https://www.cnblogs.com/snailhuang/p/12163413.html
Copyright © 2011-2022 走看看