View class source code analysis part of CBV in Django

Class-based view CBV-

CBV basic writing:

views.py in writing:

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 writing:

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

login.html code:

<!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>

Start the project, using a browser request url: 127.0.0.1:8000/login/, and shows the result (in this case, a GET request)

When the submit button is clicked, seen from login.html code form is the form used in a POST request, obtain the following results:

Request reach django django middleware will first perform in the method, and then perform the routing matches.

After the completion of the route match, performs the method as_view CBV class.

But this time, we define the class and did not as_view method, it will be followed by its parent View to find and use as_view method in the parent class.

django source part in the View class:

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方法

As can be seen from the view of the source, then View class defines eight methods first http request

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

[In] as_view determination method, if the requested method is not http_method_names in [], the exception will be thrown,

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

[Method] as_view view also defined method, CBV instantiated class in view of the process, and sends a request to the browser request to set properties.

The last call [dispatch] [dispatch] method and return value method to process the request:

由于self对象就是CBV实例化得到,所以会先执行自定义的CBV类中的dispatch方法。如果CBV类中没有定义dispatch方法则执行Django的View中的dispatch方法

Guess you like

Origin www.cnblogs.com/snailhuang/p/12163413.html