Django 之 CBV
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的更多相关文章
- Django的CBV与FBV
FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class base v ...
- Django的 CBV和FBV
FBV CBV 回顾多重继承和Mixin 回到顶部 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以 ...
- Django 之 CBV & FBV
FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django随笔中,一直使用的是这种方式,不再赘述. CBV CBV(class base views) ...
- Django之CBV和FBV
Django之CBV和FBV CBV和FBV是C和F的区别: C是Class,F是Function 在请求中,有GET请求和POST请求. 在写CBV时,url是可以对应一个类的,在类中,分别写出GE ...
- django中CBV
08.13自我总结 django中CBV 一.django处理业务逻辑的两种方式 FBV (function based views):使用函数来处理业务逻辑 CBV (class based vie ...
- django补充CBV和FBV模式
django补充CBV和FBV模式FBV模式---函数:经常用的方式CBV模式---类CBV中url连接时函数名后面要接.as_view()class index(views.View): @... ...
- 使用Ajax (put delete ) django原生CBV 出现csrf token解决办法
原因 django原生CBV中对于 Ajax put 或 delete 请求进行封装时,会把请求数据放在 request.body里, 所以获取不到csrf token 方式一: 关闭csrf 中间件 ...
- Django 的 cbv
Django 的 cbv 正如我们了解到的,Django 写视图函数有两种写法:cbv 和 fbv.cbv 提倡使用类来写,fbv 使用函数来 写.当然为了代码的重复行,官方更推荐使用 cbv. 写 ...
- django中CBV源码分析
前言:Django的视图处理方式有两种: FBV(function base views) 是在视图里基于函数形式处理请求. CBV(class base views)是在视图里基于类的形式处理请求. ...
- Django之 CBV和FBV
FBV FBV(function base views) 就是在视图里使用函数处理请求. CBV CBV(class base views) 就是在视图里使用类处理请求. Python是一个面向对象的 ...
随机推荐
- SDSC 2018 day2解题报告
目录 10.12考试总结 T1 最近公共祖先 错误原因 T2 即时战略 T3 欧皇 10.12考试总结 T1 最近公共祖先 预估得分: 100 实际得分: 20 最大得分: 100 用时:1小时10分 ...
- About Her
突然想给黑寡妇写点儿东西......(也许很多都不是我写的,但是能表达我的心意) 1. 众人进量子领域前最后一句话是她笑着说"一分钟后见." 而最终没有回来的,只有她自己一个 2. ...
- day 16
Weep no more, no sigh, nor groan. Sorrow calls no time that's gone. 别哭泣,别叹息,别呻吟:悲伤唤不回流逝的时光.
- 学好Python后可从事岗位+学习Python的难度
一.学好Python好就业: 1.Linux运维.Linux运维是必须而且一定要掌握Python语言,Python可以满足Linux运维工程师的工作需求提升效率,总而提升自己的能力.用Python实现 ...
- 第08组 Beta冲刺(3/5)
队名:955 组长博客:点这里! 作业博客:点这里! 组员情况 组员1(组长):庄锡荣 过去两天完成了哪些任务 文字/口头描述 ? 维持进度,检查需求 展示GitHub当日代码/文档签入记录 接下来的 ...
- Android studio中怎么导入android.support.v4包
Android studio中怎么导入android.support.v4包 1.File点击选择projectStructure选择对应的APP然后点击Dependencies 2.点击+号,点击第 ...
- Javascript Asynchronous Investigation
介绍 同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务: 异步任务:不进入主线程,而进入任务队列中的任务,只有任务队列通知主线程,某个异步任务可以执行了,这个任务才会进入 ...
- 【2019年05月13日】A股ROE最高排名
个股滚动ROE = 最近4个季度的归母净利润 / ((期初归母净资产 + 期末归母净资产) / 2). 查看更多个股ROE最高排名. 兰州民百(SH600738) - 滚动ROE:86.45% - 滚 ...
- Java stream 并发应用案例
在磁盘目录下有几十个txt文件,里面存储着XML格式的数据,每个文件在2-3M左右,现在需要将以上文件解析出来保存到mysql数据库,总数据量大概在30万条左右. (1)首先通过stream并发解析T ...
- Maven 教程(14)— Maven聚合与继承
原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79553011 1.Maven聚合 我们在平时的开发中,项目往往会被划分为好几个模 ...