span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }.cm-searching {background: #ffa; background: rgba(255, 255, 0, .4);}.cm-force-border { padding-right: .1px; }@media print { .CodeMirror div.CodeMirror-cursors {visibility: hidden;}}.cm-tab-wrap-hack:after { content: ""; }span.CodeMirror-selectedtext { background: none; }.CodeMirror-activeline-background, .CodeMirror-selected {transition: visibility 0ms 100ms;}.CodeMirror-blur .CodeMirror-activeline-background, .CodeMirror-blur .CodeMirror-selected {visibility:hidden;}.CodeMirror-blur .CodeMirror-matchingbracket {color:inherit !important;outline:none !important;text-decoration:none !important;}.CodeMirror-sizer {min-height:auto !important;}
-->
li {list-style-type:decimal;}.wiz-editor-body ol.wiz-list-level2 > li {list-style-type:lower-latin;}.wiz-editor-body ol.wiz-list-level3 > li {list-style-type:lower-roman;}.wiz-editor-body li.wiz-list-align-style {list-style-position: inside; margin-left: -1em;}.wiz-editor-body blockquote {padding: 0 12px;}.wiz-editor-body blockquote > :first-child {margin-top:0;}.wiz-editor-body blockquote > :last-child {margin-bottom:0;}.wiz-editor-body img {border:0;max-width:100%;height:auto !important;margin:2px 0;}.wiz-editor-body table {border-collapse:collapse;border:1px solid #bbbbbb;}.wiz-editor-body td,.wiz-editor-body th {padding:4px 8px;border-collapse:collapse;border:1px solid #bbbbbb;min-height:28px;word-break:break-word;box-sizing: border-box;}.wiz-editor-body td > div:first-child {margin-top:0;}.wiz-editor-body td > div:last-child {margin-bottom:0;}.wiz-editor-body img.wiz-svg-image {box-shadow:1px 1px 4px #E8E8E8;}.wiz-hide {display:none !important;}
-->

引入:

        近期参与的项目是一个14年基于Django开发的web系统,因为项目早期的同事并未考虑前后端分离也未遵循标准的restful接口设计,现在在逐渐拆分微服务的过程深深感到遵从标准restful设计的重要性。在这里和大家分享一下自己的拙见: 
        拿到手的项目全部基于FBV(function base views)设计,这样的设计导致的情况就是会有一堆url,一个url路由映射一个function,一个function完成一个功能,比如一下例子:
        
 
 
 
 
 
 
 
 
 
 
 
1
# urls.py
2
3
urlpatterns = [
4
    url(r'^create_book/$', views.create_book),
5
    url(r'^update_book/$', views.update_book),
6
    url(r'^get_book/$', views.get_book),
7
    url(r'^delete_book/$', views.delete_book),
8
9
    url(r'^create_author/$', views.create_author),
10
    url(r'^update_author/$', views.update_book),
11
    url(r'^get_author/$', views.get_author),
12
    url(r'^delete_author/$', views.delete_author),
13
14
]
 
 
        
# views.py
import json
from django.shortcuts import HttpResponse

def create_book(request):
return HttpResponse(json.dumps({'code': '20000'}))

def update_book(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

def get_book(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

def delete_book(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

def create_author(request):
return HttpResponse(json.dumps({'code': '20000'}))

def update_author(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

def get_author(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

def delete_author(request):
# do something
return HttpResponse(json.dumps({'code': '20000'}))

 
 
 
 
 
 
 
 
 
 
 
1
# views.py
2
import json
3
from django.shortcuts import HttpResponse
4
5
6
def create_book(request):
7
    return HttpResponse(json.dumps({'code': '20000'}))
8
9
10
def update_book(request):
11
    # do something
12
    return HttpResponse(json.dumps({'code': '20000'}))
13
14
15
def get_book(request):
16
    # do something
17
    return HttpResponse(json.dumps({'code': '20000'}))
18
19
20
def delete_book(request):
21
    # do something
22
    return HttpResponse(json.dumps({'code': '20000'}))
23
24
25
def create_author(request):
26
    return HttpResponse(json.dumps({'code': '20000'}))
27
28
29
def update_author(request):
30
    # do something
31
    return HttpResponse(json.dumps({'code': '20000'}))
32
33
34
def get_author(request):
35
    # do something
36
    return HttpResponse(json.dumps({'code': '20000'}))
37
38
39
def delete_author(request):
40
    # do something
41
    return HttpResponse(json.dumps({'code': '20000'}))
 
 
        其实单纯的从功能实现来看,这种写法完全没有问题,但是有人问题就在于接口过多,不容易维护,前端开发者会很头疼,要记下如此多的接口
        那能不能讲url简化?当然可以,或者有的项目中会出现以下实现方式:
# urls.py
urlpatterns = [
url(r'^book/$', views.book),
url(r'^author/$', views.author),
]

 
 
 
 
 
 
 
 
 
 
 
1
# urls.py
2
urlpatterns = [
3
    url(r'^book/$', views.book),
4
    url(r'^author/$', views.author),
5
]
 
 
 
# views.py
def book(request):
if request.method == "GET":
# get a book
return HttpResponse(json.dumps({'code': '20000'}))
elif request.method == "POST":
# create a book
return HttpResponse(json.dumps({'code': '20000'}))
elif request.method == "PUT":
# update a book
return HttpResponse(json.dumps({'code': '20000'}))
elif request.method == "DELETE":
# delete a book
return HttpResponse(json.dumps({'code': '20000'}))
else:
# method not be support
return HttpResponse(json.dumps({'code': '40010'}))

def author(request):
if request.method == "GET":
# get a author
return HttpResponse(json.dumps({'code': '20000'}))
elif request.method == "POST":
# create a author
return HttpResponse(json.dumps({'code': '20000'}))
elif request.method == "PUT":
# update a author
return HttpResponse(json.dumps({'code': '20000'}))
elif rrequest.method == "DELETE":
# delete a author
return HttpResponse(json.dumps({'code': '20000'}))
else:
# method not be support
return HttpResponse(json.dumps({'code': '40010'}))

 
 
 
 
 
 
 
 
 
 
 
1
# views.py
2
def book(request):
3
    if request.method == "GET":
4
        # get a book
5
        return HttpResponse(json.dumps({'code': '20000'}))
6
    elif request.method == "POST":
7
        # create a book
8
        return HttpResponse(json.dumps({'code': '20000'}))
9
    elif request.method == "PUT":
10
        # update a book
11
        return HttpResponse(json.dumps({'code': '20000'}))
12
    elif request.method == "DELETE":
13
        # delete a book
14
        return HttpResponse(json.dumps({'code': '20000'}))
15
    else:
16
        # method not be support
17
        return HttpResponse(json.dumps({'code': '40010'}))
18
19
20
def author(request):
21
    if request.method == "GET":
22
        # get a author
23
        return HttpResponse(json.dumps({'code': '20000'}))
24
    elif request.method == "POST":
25
        # create a author
26
        return HttpResponse(json.dumps({'code': '20000'}))
27
    elif request.method == "PUT":
28
        # update a author
29
        return HttpResponse(json.dumps({'code': '20000'}))
30
    elif rrequest.method == "DELETE":
31
        # delete a author
32
        return HttpResponse(json.dumps({'code': '20000'}))
33
    else:
34
        # method not be support
35
        return HttpResponse(json.dumps({'code': '40010'}))
 
 
       这里可以看到url是已经简化了,所有的功能都在function中做了实现,通过requests.method选择对应的处理逻辑
        通过postman测试一下:
        GET:
                
 

        POST:            
                
       
   PUT,DELETE和POST请求的结果是一样的,因为django的csrf验证阻止我们的请求,这里先不做csrf token验证,为了方便先将csrf token中间件注释掉:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)

 
 
 
 
 
 
 
 
 
 
 
1
MIDDLEWARE_CLASSES = (
2
    'django.contrib.sessions.middleware.SessionMiddleware',
3
    'django.middleware.common.CommonMiddleware',
4
    #'django.middleware.csrf.CsrfViewMiddleware',
5
    'django.contrib.auth.middleware.AuthenticationMiddleware',
6
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
7
    'django.contrib.messages.middleware.MessageMiddleware',
8
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
9
    'django.middleware.security.SecurityMiddleware',
10
)
 
 
            接下来重新提交,就可以返回正确的response了。     
 
       好像是达到了简化ur的l目的,但是还是通过FBV方式实现的接口,function体的内容过多,逻辑分支很多,要对请求进行判断并且实现对应的逻辑分支。代码整体上并不优雅,但是这样的代码有问题吗?并没有,只是CBV提供了更好的方式来实现接口的定义。
       我们知道FBV就是在视图里使用函数处理请求。其实CBV就是在视图里使用类处理请求。
       如果我们要通过类的方式处理请求,那上面的function就应该用以下方式实现:
# views.py
from django.views.generic.base import View
class Book(View):
def get(self, request):
# get a book
return HttpResponse(json.dumps({'code': '20000'}))

def post(self, request):
# create a book
return HttpResponse(json.dumps({'code': '20000'}))

def put(self, request):
# update a book
return HttpResponse(json.dumps({'code': '20000'}))

def delete(self, request):
# delete a book
return HttpResponse(json.dumps({'code': '20000'}))

 
 
 
 
 
 
 
 
 
 
 
1
# views.py
2
from django.views.generic.base import View
3
class Book(View):
4
    def get(self, request):
5
        # get a book
6
        return HttpResponse(json.dumps({'code': '20000'}))
7
8
    def post(self, request):
9
        # create a book
10
        return HttpResponse(json.dumps({'code': '20000'}))
11
12
    def put(self, request):
13
        # update a book
14
        return HttpResponse(json.dumps({'code': '20000'}))
15
16
    def delete(self, request):
17
        # delete a book
18
        return HttpResponse(json.dumps({'code': '20000'}))
 
 
        这里我们继承了View,并且在Book类中定义了get,post,put,delete方法,我们其实,当一个请求过来的时候会交给对应的方法进行处理,比如,我们有一个请求是GET请求,那就应该交给get方法处理,那这是怎么实现的呢?    
        我们知道在django中,一个请求的生命周期:
#1.wsgi,请求封装后交给web框架 (Flask、Django)     
#2.中间件,对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session     - 
#3.路由匹配 根据浏览器发送的不同url去匹配不同的视图函数    
#4.视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、templates => 渲染     - 
#5.中间件,对响应的数据进行处理。 
#6.wsgi,将响应的内容发送给浏览器。
     FBV和CBV在前两步是没有什么区别的,重点就在于第三步路由匹配:
     FBV中路由匹配
            url(r'^book/$', views.book),看上去很容易理解,将url是/book/的请求交给views.py中的book函数处理
     CBV中路由匹配
            url(r'^book/$', Book.as_view(), name='book'), Book是我们在views.py中定义的类,继承于View,那as_view()是从哪来的?我们没有在book中定义,而是父类(View)中定义的.
     CBV是怎么将method交给对应方法处理的呢?来看源码:
          
     as_view是一个闭包函数,返回值是内部view,我们只需要关心view部分,这里的request就是之前在FBV中使用的request,前几行就是将参数封装到类属性,重点在于self.dispatch,所有到CBV的请求都会以dispatch为入口,这里的self就是我们上面定义的Book类,
     先会在Book类中找dispatch方法,我们没有定义,所以向上找,就用Book类的父类APIView类的despatch方法,接下来我们看APIView类的dispatch都做了什么:
    

    这里的self.initialize_request做了什呢?注意看参数,(request, *args, **kwargs)这里的request是原本FBV中的第一个参数,那这个request参数是怎么来的?
    request由来:当一个页面被请示时,Django创建一个包含请求元数据的HttpRequest对象。然后Django调入合适的视图,把HttpRequest作为视图函数的第一个参数传入。每个视图要负责返回一个HttpResponse对象。
    initialize_request()分析:

    这里将原先的requet封装于Request类中
    这里标记的3处,分别对应解析器,认证器,渲染器,这里先讲get_authenticators.请看下文
 
    
    
      
 
    
 

 
                   
        

从FBV到CBV一(开始)的更多相关文章

  1. python 视图 (FBV、CBV ) 、Request 和Response对象 、路由系统

    一.FBV和CBV1.基于函数的view,就叫FBV(Function Based View) 示例: def add_book(request): pub_obj=models.Publisher. ...

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

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

  3. django——FBV与CBV

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

  4. Django之FBV与CBV

    一.FBV与CBV FBV(function based views),即基于函数的视图:CBV(class based views),即基于类的视图,也是基于对象的视图.当看到这个解释时,我是很萌的 ...

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

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

  6. 一、虚拟环境.二、路由配置主页与404.三、2.x路由分发.四、伪静态.五、request对象.六、FBV与CBV.七、文件上传.

    一.虚拟环境 ''' 解决版本共存 1. 用pycharm选择File点击NewProject然后选择virtualenv创建一个纯净环境 2. 打开下载的目录将venv文件夹下的所有文件(纯净的环境 ...

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

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

  8. django中的FBV和CBV

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

  9. Django FBV和CBV -

    一.FBV和CBV 在Python菜鸟之路:Django 路由.模板.Model(ORM)一节中,已经介绍了几种路由的写法及对应关系,那种写法可以称之为FBV: function base view ...

  10. django中视图处理请求方式(FBV、CBV)

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

随机推荐

  1. SVN+MAVEN项目打包

    题记:项目打包bash脚本 环境准备 maven版本:3.5.2 mvn -v #查看maven的版本信息 svn版本:1.4.0 svn --version #查看svn版本信息 1.update_ ...

  2. 小D课堂 - 新版本微服务springcloud+Docker教程_2_02 微服务核心基础讲解

    笔记 2.微服务核心基础讲解     简介:讲解微服务核心知识 :网关.服务发现注册.配置中心.链路追踪.负载均衡器.熔断         1.网关:路由转发 + 过滤器                ...

  3. 阶段3 3.SpringMVC·_04.SpringMVC返回值类型及响应数据类型_3 响应之返回值是void类型

    定义先的标签 返回void 测试默认的跳转 虽然是404但是方法执行了. 默认请求了 testVoid.jsp这个页面.请求路径叫什么 就访问哪个jsp页面. 使用request请求转发 抛出的异常 ...

  4. c# Selenium ExpectedConditions 不存在

    Selenium中的显示等待指的是,等待某一元素出现或者等待页面加载完成后,才执行下一步.需要用到WebDriverWait类. 例如: , , )); var element = wait.Unti ...

  5. go 基础 处理异常

    package main import "fmt" func main() { dosomething() } func dosomething(){ defer func() { ...

  6. 使用 QQ 邮箱发送邮件报错:java.net.SocketTimeoutException: Read timed out. Failed messages: javax.mail.MessagingException: Exception reading response

    使用 QQ 邮箱发送邮件报错:java.net.SocketTimeoutException: Read timed out. Failed messages: javax.mail.Messagin ...

  7. 外国前端收费模板wrapbootstrap

    https://wrapbootstrap.com/ 新闻模板 http://wrapbootstrap.com/preview/WB037B6R2

  8. appium+python+windows环境配置

    一.安装node.js 1:先找到对于电脑合适的node版本进行下载. 我的云盘node版本是7.8.0.地址如下:https://pan.baidu.com/s/19kcpXhCN1AuJAT9CB ...

  9. php 通过mysqli 操作数据库mysql

    目录 php mysqli 操作数据库 连接数据库 通过mysqli 创建数据库 通过mysqi 创建数据表 通过mysqli向数据表中插入信息 通过mysqli 读取数据 where语句的应用 通过 ...

  10. 基于nodeJS的小说爬虫实战

    背景与需求分析 最近迷恋于王者荣耀.斗鱼直播与B站吃播视频,中毒太深,下班之后无心看书. 为了摆脱现状,能习惯看书,我开始看小说了,然而小说网站广告多而烦,屌丝心态不愿充钱,于是想到了爬虫. 功能分析 ...