Django 中有两种编写方式,FBV 和 CBV,那么什么是 FBV,CBV 又是什么呢?

一、什么是 CBV

  • FBV(function base views) 就是在视图里使用函数处理请求(常见)。
  • CBV(class base views) 就是在视图里使用类处理请求。

示例:

1、project/urls.py

from django.contrib import admin
from django.urls import path
from app.views import IndexView urlpatterns = [
path('admin/', admin.site.urls),
path('index/', IndexView.as_view()),
]

2、app/views.py

from django.shortcuts import render, HttpResponse
from django.views import View class IndexView(View):
def get(self, request, *args, **kwargs):
print('get')
return HttpResponse('GET') def post(self, request, *args, **kwargs):
print('post')
return HttpResponse('POST')

可以看到所有的请求都是在类 IndexView 中处理的,它继承 View,不管是什么请求,都可以匹配到。

二、源码分析

1、CBV 在进行路由匹配时,执行 as_view() 方法,它是类 View 中的一个方法,源码 base.py

class View:
@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

2、从上面的源码中我们可以看到 as_view(),返回 view() 方法。而 view() 又调用执行 self.dispatch(request, *args, **kwargs) 方法:

def dispatch(self, request, *args, **kwargs):
"""
首先要判断请求方法是不是在 self.http_method_names 中(即允许的方法列表中)
通过反射,匹配相应方法 get、post、put、delete 等
"""
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) # 如果匹配上了,就执行它,get(requesr, *args, **kwargs)

http_method_names

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

3、因此大致的执行流程为:

  • 请求过来先执行 URL 中的 as_view() 方法
  • as_view() 返回 view() 方法
  • view() 方法又调用执行 dispatch() 方法
  • dispatch() 中通过反射的方式来匹配相应的请求,是 get 请求,就执行 get() 方法,如果是 post 请求的就执行 post() 方法。

三、重写 dispatch

从上面我们指定 CBV 中,请求过来,执行相应视图函数之前,都会先执行 dispatch() 方法。那么如果我们想在处理请求前执行某个方法或者就打印点别的东西,我们可以重写它。

方法一

from django.shortcuts import render, HttpResponse
from django.views import View class IndexView(View):
def dispatch(self, request, *args, **kwargs):
print('before...')
func = getattr(self, request.method.lower())
ret = func(self, request, *args, **kwargs)
print('after...')
return ret def get(self, request, *args, **kwargs):
print('get')
return HttpResponse('GET') def post(self, request, *args, **kwargs):
print('post')
return HttpResponse('POST')

运行结果如下:

before...
get
after...

当有很多个类的时候,不可能每个类都写一个,可以写一个基类,其他类继承基类即可:

class BasePatch(object):
def dispatch(self, request, *args, **kwargs):
print('before...')
func = getattr(self, request.method.lower())
ret = func(self, request, *args, **kwargs)
print('after...')
return ret class IndexView(BasePatch, View):
pass

这样 IndexView 就会先去找基类 BaseView 中的 dispatch() 方法,而不是 View 中的。


方法二

也可以继承父类的 dispatch(),不用自己写反射逻辑:

class BasePatch(object):
def dispatch(self, request, *args, **kwargs):
print('before...')
ret = super(BasePatch, self).dispatch(request, *args, **kwargs)
print('after...')
return ret

四、CSRF

CBV 中如果想给某个函数免除 csrf_token 认证,可以通过装饰器的形式实现,但是需要注意的是,装饰器必须装饰在类上或者 dispatch 上

方法一

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt class IndexView(View):
@method_decorator(csrf_exempt) # 这句
def dispatch(self, request, *args, **kwargs):
print('before...')
func = getattr(self, request.method.lower())
ret = func(self, request, *args, **kwargs)
print('after...')
return ret

方法二

装饰在类上,不用 dispatch

@method_decorator(csrf_exempt, name='dispatch')
class IndexView(View):
def get(self, request, *args, **kwargs):
pass

Django 之 CBV的更多相关文章

  1. Django的CBV与FBV

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

  2. Django的 CBV和FBV

    FBV CBV 回顾多重继承和Mixin 回到顶部 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以 ...

  3. Django 之 CBV & FBV

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

  4. Django之CBV和FBV

    Django之CBV和FBV CBV和FBV是C和F的区别: C是Class,F是Function 在请求中,有GET请求和POST请求. 在写CBV时,url是可以对应一个类的,在类中,分别写出GE ...

  5. django中CBV

    08.13自我总结 django中CBV 一.django处理业务逻辑的两种方式 FBV (function based views):使用函数来处理业务逻辑 CBV (class based vie ...

  6. django补充CBV和FBV模式

    django补充CBV和FBV模式FBV模式---函数:经常用的方式CBV模式---类CBV中url连接时函数名后面要接.as_view()class index(views.View): @... ...

  7. 使用Ajax (put delete ) django原生CBV 出现csrf token解决办法

    原因 django原生CBV中对于 Ajax put 或 delete 请求进行封装时,会把请求数据放在 request.body里, 所以获取不到csrf token 方式一: 关闭csrf 中间件 ...

  8. Django 的 cbv

    Django 的 cbv 正如我们了解到的,Django 写视图函数有两种写法:cbv 和 fbv.cbv 提倡使用类来写,fbv 使用函数来 写.当然为了代码的重复行,官方更推荐使用 cbv. 写 ...

  9. django中CBV源码分析

    前言:Django的视图处理方式有两种: FBV(function base views) 是在视图里基于函数形式处理请求. CBV(class base views)是在视图里基于类的形式处理请求. ...

  10. Django之 CBV和FBV

    FBV FBV(function base views) 就是在视图里使用函数处理请求. CBV CBV(class base views) 就是在视图里使用类处理请求. Python是一个面向对象的 ...

随机推荐

  1. 有这样一个url=http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段js程序提取url 中的各个get参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中, 如{a:'1',b:'2',c:'',d:'xxx',e:undefined}

    第一种方法: console.log(getJson(url)); function getJson(url){ var obj={}; var arr=url.split("?" ...

  2. 【可持久化0/1Trie】【P4735】最大异或和

    Description 给定一个长度为 \(n\) 的序列 \(A\),有 \(m\) 次操作,每次要么在序列尾部再添加一个数,将序列长度 \(n\) 加一,要么给进行一次查询,给定查询参数 \(l, ...

  3. 远程windows

    1. 起因 因为经常用teamviewer,所以断定我是商业用户,不允许我用了.想买一个授权,结果太贵了,1700多.使用了很多其他的,向日葵卡顿,有的窗口点不到,vnc慢,效果差,卡顿,还收费,等等 ...

  4. SuperMemo

    SuperMemo Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is ...

  5. 蚂蚁花呗5面面试真题,你敢来挑战一下吗?(Java岗)

    蚂蚁花呗一面(一个小时): JDK 中有哪几个线程池?顺带把线程池讲了个遍 Java容器有哪些?哪些是同步容器,哪些是并发容器? ArrayList和LinkedList的插入和访问的时间复杂度? j ...

  6. sqlException 使用relace 替换单引号

    我们从前端输入数据的时候,可能会输入一些 单引号 ,的字符 导致直接进行执行sql 语句保存的时候出现错误 如: 输入的有 单引号 保存按钮小代码 <asp:Button ID="bt ...

  7. Effective.Java第23-33条(泛型相关)

    23.  类结构层次优于标签类 有时你会碰到一个类,它的实例有一个或多个风格,并且包含一个tag属性表示实例的风格.例如,如下面的类表示一个圆或者矩形: public class Figure { / ...

  8. 【题解】分离与合体 [Loj10151]

    [题解]分离与合体 [Loj10151] 传送门:分离与合体 \([Loj10151]\) [题目描述] 给定一个长度为 \(n\) 的序列,如果从某个点 \(k\) 处将区间 \([l,r]\) 断 ...

  9. TestNG系列(五)TestNG测试报告

    以TestNG执行测试方法后会生成test-output测试结果集,其中index.html是测试结果的展示.TestNG的测试报告可以通过IReporter监听自定义,也可以通过第三方工具(Repo ...

  10. - Permission 运行时权限 总结 翻译 MD

    目录 目录 对运行时权限的一些理解 运行时权限使用案例 开源库:PermissionsDispatcher 注解 使用案例 使用步骤 测试代码 自动生成的类 官方文档:请求权限 Add permiss ...