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. 【CSP-S膜你考】那23个路口

    那23个路口 题面 故事的起源不加赘述,那23个路口. 单刀直入,我直接说题的意思. 蚊子和疯子在做一件事,就是他们要在茫茫的大街上找一个出发点,然后从出发点开始,经过上下左右23次拐弯,到达一个他们 ...

  2. Error Code: 1175. You are using safe update

    使用MySQL执行update的时候报错:Error Code: 1175. You are using safe update mode and you tried to update a tabl ...

  3. Shell脚本之九 输入输出重定向和文件包含

    输出重定向:是指不使用系统提供的标准输入端口来输出,而是重新指定其他来进行输出.例如在终端输入的字符串本来是要输出到终端屏幕上的,但可以将输出指定为其他文件,将输入字符串输出到该文件中,而不再是屏幕上 ...

  4. [JS]截取字符,中英文都可以

    //截取字符,中英文都可以,hasDot=true 返回值的最后还可以添加3个点 function subString(str, len, hasDot) { var newLength = 0; v ...

  5. 日志篇 随着win10更新...

    随着win10更新到最新..我发现电脑出了点状况.. 一 是电脑睡眠主机不关闭...然后用了 https://jingyan.baidu.com/article/cb5d6105d76343005c2 ...

  6. Spring JPA事务

    目录 1. 概述 促进阅读: 2. 配置不带XML的事务 3. 使用XML配置事务 4. @Transactional 注解 5. 潜在的陷阱 5.1. 事务和代理 5.2. 更改隔离级别 5.3. ...

  7. 设置KAFKA

    让我们继续下载并设置Kafka,启动zookeeper,集群,生产者和消费者.   要下载Kafka,请参阅此链接  http://kafka.apache.org/downloads.html 下载 ...

  8. 2019 C/C++《阿里》面试题总结

    一.C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛. C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构化语言 ...

  9. Java学习:字符串概述与特点

    字符串概述与特点 java.lang.String类 代表字符串 API当中说:Java程序中的所有字符串字面值(如“abc“)都作为此类的实例实现.其实就是说:程序当中所用的双引号字符串,都是Str ...

  10. GoF的23种设计模式之创建型模式的特点和分类

    创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”.这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成.就像我们去商场购买商品时, ...