Django----FBV 与 CBV 介绍、CBV源码分析

Django----FBV 与 CBV 介绍、CBV源码分析,第1张

文章目录
  • 一、CBV和FBV
  • 二、CBV 源码分析

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

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

一、CBV和FBV

FBV:基于函数的视图;

CBV:基于类的视图;

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 需要继承view

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()),

基于 CBV 与 FBV 的不同之处,分析CBV 的运行原理


 
 

二、CBV 源码分析

使用 CBV 时,需要 通过 视图类. as_view() 才能进行路由匹配,那么直接观察这个as_view()的源码

首先,as_view() 是一个绑定给 类的方法

其次,由于url中是加上括号调用了 as_view() ,所以,观察返回值能够发现,返回的是内部的一个view函数

**至此,我们简化一下,AddClass.as_view() 运行的结果就是view; 所以 views.AddClass.as_view()=views.view **

# urls.py中其本质就是
url(r'^add_class/$', views.view),

所以 CBV 路由匹配的本质,就是 FBV


接下来,我们分析一下,当路由匹配成功时,需要执行的这个view函数的源码

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/")
    @classonlymethod
    def as_view(cls, **initkwargs):
				... ... # 源码省略

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)  ----->  '实例化生成一个对象'
            if hasattr(self, 'get') and not hasattr(self, 'head'): 
                self.head = self.get ----> '给生成的对象添加 head 属性'
            self.request = request  ----> '给生成的对象添加 request 属性'
            self.args = args  ----> '给生成的对象添加 args 属性'
            self.kwargs = kwargs  ----> '给生成的对象添加 args 属性'
            return self.dispatch(request, *args, **kwargs) 
				... ... # 源码省略
        return view

最为重要的部分就是 return self.dispatch(request, *args, **kwargs)

由于,对象 和 产生对象的AddClass类中都没有 dispatch函数,所有需要到AddClass的父类view中去找

  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
  
  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)

判断当前请求的方法是否符合 8 个 默认的请求方法

getattr( 对象, 请求的方法(字符串), 拿不到请求方法的报错信息) --> 拿到了AddClass我们自定义类的 get方法

最后一步就是 执行了 我们自定义的 get方法

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/917161.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存