Django之视图系统中的CBV源码分析

一、Django的View

一个视图函数(或者类),简称视图,三一个简单的python函数(类),它接收Web请求并且返回Web响应
响应可以是一张网页的HTML内容,一个重定向,一个XML文档,一个404错误或者一张图片

无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

CBV和FBV

CBV:class base view基于类写的视图view

FBV: function base view,基于函数的view

写个例子:

FBV版本:

# FBV版添加班级
def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

CBV版本:

# CBV版添加班级
from django.views import View


class AddClass(View):

    def get(self, request):
        return render(request, "add_class.html")

    def post(self, request):
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")

注意:在使用CBV时,urls.py中也要做对应的修改

# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),

总结:无论是FBV还是CBV路由层都是路由对应视图函数内存地址

Django中的CBV源码简单分析:

1、先简单写一个cbv,

# 路由层
urlpatterns = [
				url(r'^mycls/$',views.MyCls.as_view())
				
]

# 视图层
class MyCls(View):
		def get(self,request):
			return render(request,'index.html')
		def post(self,request):
			return HttpResponse('post')

问题:

  1. 路由层里MyCls.as_view()为什么本质是views.view
  2. 视图层里自定义的类MyCls是怎么处理前端的请求的?

1、首先看url

Django的CBV在url的书写需要在views.类名后加**.as_view(),从这个形式上可以看出,as.view一定是一个方法,这个方法加上了(),是在Django项目启动时就自动执行,返回值也应该是我们原来熟悉的形式(一个函数名),从而在匹配url**后就可以执行相应的视图函数。
先看一下这个as.view对应的源码

Django之视图系统中的CBV源码分析_第1张图片

由此,可以很明显的看出,Django项目启动后,CBV下的url本质执行的是
url(r'^mycls/$',views.view)

2、接下来当用户成功匹配url时,对应url的view会执行对应请求方式下的类方法

源码(下面的源码注意两个点:1、函数的闭包作用域。2,self的指向):

Django之视图系统中的CBV源码分析_第2张图片

cls:是MyCls类,self是实例化的对象

view.py: 找dispatch方法时需要先找自己类中,没有再找继承类中

class MyCls(View):
		def get(self,request):
			return render(request,'index.html')
		def post(self,request):
			return HttpResponse('post')

源码(自己的类中显然没有dispatch方法,所以去继承的类中找):

   def dispatch(self, request, *args, **kwargs):
 
        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)


Django之视图系统中的CBV源码分析_第3张图片

以上Django中的基于CBV的源码执行流程,这里面很好的利用了python面向对象的三大特性:继承,封装和多态,还有闭包函数的作用域。

参考博客

你可能感兴趣的:(Django)