Django源码理解一

Django视图CBV的dispatch相关源码解析
 
 
一般cbv视图写法:
class Foo(View):
    def get(request):
        return HttpResponse('GET')
一般路由写法:
urlpatterns = [
    # url(r‘^index/‘, views.index),
    url(r‘^index/‘, views.Index.as_view()),
]
 
Django在通过路由as_view()方法,会执行基类View中的dispatch方法,在通过dispatch方法执行具体的方法视图。
 
在这个方法中会先判断这个请求的method是否在http_metod_names列表中。
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
这个列表是http协议中的请求方法,我们也可以通过修改源码,自定义请求类型。
 
然后dispatch通过getattr,从self这个对象中找method方法(小写,因为我们试图类里都是小写的方法名),找到之后运行并传参。
    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)
 
由上面这个源码原理我们具体分析dispatch运行过程如下:
 
from django.views import View
class StudentView(View):
    def dispatch(self,request,*args,**kwargs):
        ret =super(StudentView,self).dispatch(request,*args,**kwargs)
        return ret
    def get(self,request,*args,**kwargs):
        return HttpResponse('GET')
 
总结:
1 通过视图的as_view()运行源码as_view()
as_view会return dispatch这个方法
2 执行 Student类里自己的dispatch,因为我们重写了这个方法,所以先运行自己的。
自己的这个dispatch通过super找到了源码的dispatch.
3 源码的dispatch先判断请求的method是否在http_method_names
然后通过反射getattr,找到method,这个method又回到了Student类里的具体的method方法。
4 最后运行我们重写的dispatch中的return ret返回给用户。
 
所以我们重写的这个dispatch的原理就有点像装饰器,如果我们在super之前写一个print('before'),return之前写一个print('after'),那么每次浏览器请求之前都会先打印before,返回给用户之前都会打印after。
示例如下:
from django.views import View
class StudentView(View):
    def dispatch(self,request,*args,**kwargs):
        print('before')
        ret =super(StudentView,self).dispatch(request,*args,**kwargs)
        print('after')
        return ret
 
 
 
原文地址:https://www.cnblogs.com/ArmoredTitan/p/8751679.html