Source code parsing the nature of Django CBV

Source: Internet
Author: User
The source code parsing of Django CBV mode

In general, the nature of HTTP requests is based on the socket

Django view functions can be based on the FBV mode, or can be based on the CBV mode.

The FBV-based pattern is the association of URL and view functions in the Django Routing map table, while the CBV-based pattern defines the view class in the views.py file, view functions in the view class, such as Get,post,put,delete, etc.

Create a new project with Django and create a route map

from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [    url(r'^cbv/$',views.CBV.as_view())]

The corresponding views.py file contents:

from django.shortcuts import render,HttpResponsefrom django.views import Viewclass CBV(View):    def get(self,request):        return HttpResponse("GET")    def post(self,request):        return HttpResponse("POST")

Launch the project, using the browser request URL http://127.0.0.1:8000/cbv/ , the browser displays the result as:

When a request arrives, Django executes the method in the Django middleware and then performs a routing match.

After the route match is complete, the As_view method in the CBV class is executed.

CBV does not define the as_view method, because CBV继承自Django的View , so会执行Django的View类中的as_view方法

Some source code for the As_view method of the Django view class

Class View (object): "" "intentionally simple the parent class for any views.    Only implements Dispatch-by-method and simple sanity checking. "" "Http_method_names = [' Get ', ' post ', ' Put ', ' Patch ', ' delete ', ' head ', ' Options ', ' Trace '] def __init__ (self, **k Wargs): "" "Constructor. called in the URLconf;        can contain helpful extra keyword arguments, and other things.        "" "# Go through keyword arguments, and either save their values to We # instance, or raise an error. For key, value in Six.iteritems (Kwargs): SetAttr (self, key, value) @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 key                                Word%r. As_view "" Only accepts arguments that is already " "Attributes of the class"% (cls.__name__, key)) def view (Request, *args, **kwargs): Self = CLS (**ini            Tkwargs) 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 C Srf_exempt from Dispatch update_wrapper (view, Cls.dispatch, assigned= ()) return view

From the view source can be seen, in the view class, the first definition of the HTTP request eight ways

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

In the as_view方法 judgment, if the requested method is not in http_method_names , an exception is thrown,这里的cls实际上指的是自定义的CBV类

The view method is then defined in the As_view method to instantiate the CBV class in the View method, get the Self object, and then encapsulate the request requests sent by the browser in the Self object

self = cls(**initkwargs)

Finally, the dispatch method in the Self object is called and the value of the dispatch method is returned to process the request

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

The dispatch method source in Django View

class View(object):    """    中间省略    """    def dispatch(self, request, *args, **kwargs):        # Try to dispatch to the right method; if a method doesn't exist,        # defer to the error handler. Also defer to the error handler if the        # request method isn't on the approved list.        if request.method.lower() in self.http_method_names:            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)        else:            handler = self.http_method_not_allowed        return handler(request, *args, **kwargs)

In the dispatch method, convert the Request.method to lowercase to determine if Request.method is present in Http_method_names if it is in the defined http_method_names. The getattr reflex is used to get the handler

In the dispatch method here, self refers to the object that is instantiated by the custom CBV class

Get the Request.method corresponding method from the CBV class, then execute the method in CBV and return

From this, you can know如果在Django项目中使用CBV的模式,实际上调用了getattr的方式来执行获取类中的请求方法对应的函数

Conclusion:

CBV基于反射实现根据请求方式不同,执行不同的方法
Customizing the Dispatch method

If you want to perform some action when requesting a URL in a project that is based on CBV mode, you can define the dispatch method in the class that corresponds to the URL

Modify the views.py file

class CBV(View):    def dispatch(self, request, *args, **kwargs):        func = getattr(self,request.method.lower())        return func(request,*args,**kwargs)    def get(self,request):        return HttpResponse("GET")    def post(self,request):        return HttpResponse("POST")

You can also override the dispatch method with inheritance:

class CBV(View):    def dispatch(self, request, *args, **kwargs):        print("before")        res = super(CBV, self).dispatch(request, *args, **kwargs)        print("after")        return res    def get(self,request):        return HttpResponse("GET")    def post(self,request):        return HttpResponse("POST")

To refresh the browser, the Django spooling results are as follows:

Browser page Results

Similarly, if there are multiple classes based on CBV, and there are multiple classes of shared functionality, to avoid duplication, you can define a class individually, override the dispatch method in this class, and then inherit the class from the view class that corresponds to the URL.

Modify the urls.py file

from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [    url(r'^cbv1/$',views.CBV1.as_view()),    url(r'^cbv2/$',views.CBV2.as_view()),]

views.py File Contents

from django.shortcuts import render,HttpResponsefrom django.views import Viewclass BaseView(object):    def dispatch(self, request, *args, **kwargs):        func = getattr(self, request.method.lower())        return func(request, *args, **kwargs)class CBV1(BaseView,View):    def get(self,request):        return HttpResponse("CBV1 GET")    def post(self,request):        return HttpResponse("CBV1 POST")class CBV2(BaseView,View):    def get(self,request):        return HttpResponse("CBV2 GET")    def post(self,request):        return HttpResponse("CBV2 POST")

Python-oriented objects let you know that when a request arrives at a view class, the dispatch methods in the CBV1 and CBV2 classes are executed first, but there is no CBV2 method in the CBV1 and dispatch classes, and the dispatch method is found in the parent class in order. The dispatch method in the Baseview class is executed at this point.

Browser request URL http://127.0.0.1:8000/cbv1/ , browser page display

Browser request URL http://127.0.0.1:8000/cbv2/ , browser page display

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.