• FBV与CBV, CBV源码剖析


    目录

    FBV和VBC

    CBV和FBV

    CBV源码分析

    CBV源码简述


    FBV和VBC

    一个视图函数(类),简称视图, 是一个简单的python函数(类),他接受web请求并且返回web响应.

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

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

    CBV和FBV

    FBV function base view: 基于函数的视图

    CBV class base view : 基于类的视图

    FBV版添加班级

    1. def add_class(request):
    2. if request.method == 'POST':
    3. class_name = request.POST.get('class_name')
    4. models.Classes.objects.create(name=class_name)
    5. return redirect('/class_list/')
    6. return render(request,'add_class.html')

    CBV版本添加班级

    CBV需要继承view类

    1. from django.views import View
    2. class AddClass(View):
    3. def get(self, request):
    4. return render(request,add_class.html')
    5. def post(self, request):
    6. class_name = request.POST.get('class_name')
    7. models.Class.objects.create(name=class_name)
    8. return redirect('/class_list/')

    使用CBV时, urls.py中也做对应的修改

    url(r'^add_class/$', views.AddClass.asview()),

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

    CBV源码分析

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

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

    也就是说 AddClass.as_view() 运行的结果是view, 所以views.AddClass.as_view() = views.view

    url(r'^add_class/$',views.vies),

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

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

    1. from django.views import View
    2. class AddClass(View):
    3. def get(self,request):
    4. return render(request,'add_class.html')
    5. def post(self, request):
    6. class_name = request.POST.get('class_name')
    7. models.Classes.objects.create(name=class_name)
    8. return redirect('/class_list/')
    1. @classonlymethod
    2. def as_view(cls,**initkwargs):
    3. ...
    4. def view(request,*args,**kwargss):
    5. self = cls(**initkwargs) >>>实例化生成一个对象
    6. if hasattr(self, 'get') and not hasattr(self,'head'):
    7. self.request = self.get >>> 给生成的对象添加 head属性
    8. self.request = request >>> 给生成的对象添加 request 属性
    9. self.args = args >>> 给生成的对象添加 args 属性
    10. self.kwargs = kwargs >>> 给生成的对象添加kwargs属性
    11. return self.dispatch(request,*args,**kwargs)
    12. ...
    13. return view

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

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

    [类的名称空间查找顺序>>> 对象自身>>父类>>父类的父类]

      

    1. http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    2. def dispatch(self, request, *args, **kwargs):
    3. if request.method.lower() in self.http_method_names:
    4. handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    5. else:
    6. handler = self.http_method_not_allowed
    7. return handler(request, *args, **kwargs)

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

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

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

    CBV源码简述

    根据前端请求方式的不同自动匹配执行对应的方法-在url路由中的views.类 名.as_view()的源码下可以 看到是被@classonlymethod修饰的类方法,内部定义闭包函数传参并返回闭包函数名、在dajong启动的时候会执行urls 的as_view()产生变形为views.view,在浏览器提交请求的时候就会触发view方法,通过view下的self 使用类的对 象,返回self.dispatch属性、在父类中的dispathc函数通过反射机制就 通过字符串操作对象属性口只有在被完成后才 会真正执行,就是可以事先写好逻辑接口,事后实现接口功能

  • 相关阅读:
    栈与队列:用栈实现队列
    身份证合法验证查询易语言代码
    新建路由的过程vue-router4
    P1025 [NOIP2001 提高组] 数的划分
    Redis基础与高可用集群架构进阶详解
    vue3.2新功能
    PLG SaaS 产品 Figma 商业模式拆解
    【软考】__集成_考前20问
    antd+ Umi使用中出现的问题集合(一)
    [极客大挑战 2019]Http1(BUCTF在线评测)
  • 原文地址:https://blog.csdn.net/weixin_67531112/article/details/126708282