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. vs连接oracle

    参考: https://www.cnblogs.com/gguozhenqian/p/4262813.html

  2. javaWeb如何转发数据,jsp页面如何接收?

      1.情景展示 现在有一个需求就是:请求达到服务器后,服务器需要将请求的数据传给另一个页面,如何实现? 2.目标分析 通过服务器跳转到页面上,有两种实现方式:一种是转发,一种是重定向. 我们知道转发 ...

  3. klass-oop

    (1)Klass Klass 简单来说就是 Java 类在 HotSpot 中的 C++ 对等体,主要用于描述对象实例的具体类型.一般 JVM 在加载 class 文件时,会在方法区创建 Klass ...

  4. scala集合有哪些

    不可变集合图示:  

  5. C#内存泄露与资源释放 经验总结

    本文链接:http://blog.csdn.net/yokeqi/article/details/41083939 C#相比其他语言,拥有强大的垃圾回收机制,但并不是这样,你就可以对内存管理放任不管, ...

  6. es6 Decorator修饰器

    1.类的修饰: 修饰器(Decorator)函数,用来修改类的行为.修饰器是一个对类进行处理的函数.修饰器函数的第一个参数,就是所要修饰的目标类. @testable class MyTestable ...

  7. 040 RabbitMq及数据同步02

    1.Spring AMQP (1)简介 Spring有很多不同的项目,其中就有对AMQP的支持: Spring AMQP的页面:http://spring.io/projects/spring-amq ...

  8. AngularJS 的全选、反选实现

    目录 AngularJS 的全选.反选实现 一.需求 二.思路 三.实现 AngularJS 的全选.反选实现 一.需求 要使用 AngularJS 实现 checkbox 的全选.反选. 其中所有项 ...

  9. Hive sampling 语法之TABLESAMPLE用法理解

    官网关于LanguageManual Sampling的教程,部分截图如下,这里主要分享对TABLESAMPLE(BUCKET 3 OUT OF 16 ON id)子句的理解 ​ 官网中假设创建表时设 ...

  10. 在Windows 10中禁用自动文件夹类型发现

    点击下载注册表文件:https://files.cnblogs.com/files/Music/win10_automatic_folder_type_discovery.zip 已知Windows ...