一、FBV与CBV

  FBV(function based views),即基于函数的视图;CBV(class based views),即基于类的视图,也是基于对象的视图。当看到这个解释时,我是很萌的,我仔细回想了一下,哪里有基于类的视图啊,怎么我之前写的视图都是一个一个的函数啊,奇怪了,很多人都应该和我一样蒙(大佬除外哈)。没错我之前写的所有的视图都是基于函数的,所以今天咋们不去扯什么是FBV了,实在不知道的,可以看看在今天之前的所有视图,绝对都是FBV模型的(这个我敢打包票)。

  二、CBV的实现代码

  当听到基于class时,就会想到对象,瞬间有点慌,总感觉对象这个东西要比函数难,没有那么好理解,这应该是大多数人的共性,但在python中处处皆对象,你不想碰他就不能碰他?????不可能的,要想使你的代码更有水平,那你就避不开对象,而且对于开发来说,肯定都是要用到对象。其实哈这个基于对象的视图很好理解。

  1,先写视图

from django.shortcuts import render,HttpResponse
from django.views import View
class myview(View):
def get(self,request):
return render(request,'login.html')
def post(self,request):
return HttpResponse('post请求')

  2,写一个登录的页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<label for="user">用户名:</label>
<input type="text" name="user" id="user">
<label for="pwd">密码:</label>
<input type="password" name="pwd" id="pwd">
<input type="submit" value="提交">
</form>
</body>
</html>

  3,url

from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.myview.as_view()),
]

  4,分析过程

  首先我们得看url,当请求路径是login时,会调用views里面的myview类的一个方法as_view,在这里我们先不管这个方法到底干了啥,只是说说执行流程。在浏览器地址栏输入login路径时,用的是get请求,它就会去调用myview类下的自己写的get,然后饭后一个登录页面;得到页面后输入用户名和密码之后点击提交按钮,又往login路径发送了一个post请求,这时就会调用myview类下的自己写的post方法,返回一个‘post请求’字符,这就是整个过程,从两个流程来看,大概可以猜出,整个过程中,django会判断请求的方式,不同的请求方式调用相应的方法

  三、分析源码

  既然在我自定义的myview类里没有写任何关于请求方式的逻辑,那我们应该猜测到,在myview继承的View类里面肯定有相关的东西(大佬经验,阅读源码时,看不懂就不要去看,不要去分析,只看我们需要的)。

  1,源码

class View:
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
""" http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def __init__(self, **kwargs):
"""
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in kwargs.items():
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 keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key)) def view(request, *args, **kwargs):
self = cls(**initkwargs)
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 csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view 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) def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return HttpResponseNotAllowed(self._allowed_methods()) def options(self, request, *args, **kwargs):
"""Handle responding to requests for the OPTIONS HTTP verb."""
response = HttpResponse()
response['Allow'] = ', '.join(self._allowed_methods())
response['Content-Length'] = ''
return response def _allowed_methods(self):
return [m.upper() for m in self.http_method_names if hasattr(self, m)]

  2,剖析

  在url里面,我们可以看到当请求过来后,执行的是views.myview.as_view(),所以我们去看看as_view()这个方法到底干了啥,首先在我们自定义的myview类里面没有这个方法,那就去父类View里找。

 上面说过看不懂的就不要看,所以我把看不懂的给删除了
 @classonlymethod
def as_view(cls, **initkwargs): #这是as_view方法     def view(request, *args, **kwargs): #这是as_view方法里嵌套一个方法view
self = cls(**initkwargs) #这是用myview类实例化的一个对象self
       return self.dispatch(request, *args, **kwargs) #这是用实例化对象self去调用dispatch方法,然后作为view方法的返回值值
    return view #这是返回view这个方法,也就是把view方法的返回值作为as_view的返回值,

  接下来我们得去看看dispatch方法干了什么,首先也得从自定义的myview类里找dispatch方法,没找到,然后去父类View里找,

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):       #这是dispatch方法
if request.method.lower() in self.http_method_names: #这是把请求的方法取出来,然后小写,看有没有在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) #返回请求方式对应方法的执行结果
比如说是get请求进来后,它就利用反射会去myview里面拿到一个叫get的方法,在我的myview类下就有我自定义的get方法,然后执行它,得到一个HTTPResponse对象,返回给dispatch方法,dispatch方法又把这个HTTPResponse对选哪个返回给了view方法,
view方法又把这个对象返回给as_view方法,as_view方法又把这个作为响应返回给客户端,这整个过程简化中间的过程就会变成,get方法返回一个HTTPResponse对象给客户端

Django之FBV与CBV的更多相关文章

  1. django的FBV和CBV

    title: python djano CBV FBV tags: python, djano, CBV, FBV grammar_cjkRuby: true --- python django的fu ...

  2. django的FBV和CBV的装饰器例子

    备忘 def auth(func): def inner(request,*args,**kwargs): u = request.COOKIES.get('username111') if not ...

  3. Django之FBV和CBV的用法

    FBV FBV,即 func base views,函数视图,在视图里使用函数处理请求. 以用户注册代码为例, 使用两个函数完成注册 初级注册代码 def register(request): &qu ...

  4. Django的FBV和CB

    Django的FBV和CBV FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV C ...

  5. django请求生命周期,FBV和CBV,ORM拾遗,Git

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  6. django——FBV与CBV

    引言 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class bas ...

  7. python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  8. django基础 -- 4. 模板语言 过滤器 模板继承 FBV 和CBV 装饰器 组件

    一.语法 两种特殊符号(语法): {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 二.变量 1. 可直接用  {{ 变量名 }} (可调用字符串, 数字 ,列表,字典,对象等) ...

  9. django中的FBV和CBV

    django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...

随机推荐

  1. RQNOJ 2 开心的金明

    一道基础的01背包,要是不明白可以自己搜一下背包九讲,自己刚开始数组开小了,题目看串了行,找了半天,小错还是要格外注意的. #include <iostream> #include < ...

  2. # 2019-2020.3 《java程序设计》第一周学习总结

    2019-2020-3 <Java 程序设计>第一周学习总结 在本周的学习中,学习到了好多也收获了好多,从最基础的安装虚拟机开始,根据老师的博客中的教程一步一步的进行,在这过程中也遇到了好 ...

  3. Tomcat架构解析(五)-----Tomcat的类加载机制

    类加载器就是根据类的全限定名(例如com.ty.xxx.xxx)来获取此类的二进制字节流的代码模块,从而程序可以自己去获取到相关的类. 一.java中的类加载器   1.类加载器类别 java中的类加 ...

  4. 01-jQuery的介绍

    1.为什么要使用jQuery 在用js写代码时,会遇到一些问题: window.onload 事件有事件覆盖的问题,因此只能写一个事件. 代码容错性差. 浏览器兼容性问题. 书写很繁琐,代码量多. 代 ...

  5. openxml excel封装类

    public class ExcelUntity { #region property /// <summary> /// excel文档(相当于excel程序) /// </sum ...

  6. 冲刺博客NO.7

    今天做了什么: 在Iconfont-阿里巴巴矢量图标库找了个图标,仍感觉不是很好看. 查询函数遇到了很多困难 困难:不会真机测试,链接USB后 adb没检测到设备(包括真机和虚拟机). 在Termin ...

  7. git代码同步服务器代码需要注意的问题

    魔鬼藏在细节之中,git代码同步服务器代码需要注意的问题 1. 全文件夹覆盖  git pull 当前文件夹 2. 覆盖前做代码备份  mv origin origin_20190404_bak

  8. Autofac与AOP功能例子

    using Autofac.Extras.DynamicProxy; using System; using System.Collections.Generic; using System.Linq ...

  9. nginx 502错误 upstream sent too big header while reading response header from upstream

    原本的设置是 proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; 在这种配置下,使用fiddler进行抓包分 ...

  10. Javascript高级编程学习笔记(12)—— 引用类型(1)Object类型

    前面的文章中我们知道JS中的值分为两种类型 基础类型的值和引用类型的值 基础类型的值我已经大概介绍了一下,今天开始后面几天我会为大家介绍一下引用类型的值 Object类型 对象是引用类型的值的实例,在 ...