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