使用

关于FBV和CBV的使用在之前有提到,点击穿越

准备

首先在视图中创建一个类并继承 django.views.View 类,在类中可定义各种请求方式对应执行的函数(函数名为请求方式名称小写)。

 from django.views import View

 class TestView(View):
def get(self, request):
return HttpResponse('get') def post(self, request):
return HttpResponse('post')

配置路由。

 from django.conf.urls import url
from app import views
urlpatterns = [
url(r'^test/', views.TestView.as_view()),
]

源码

做好上述准备之后,就可以通过相应的请求方法请求对应路由地址来执行CBV视图中对应请求方法名的函数,为什么Django能帮我们做到这一点呢?我们知道,在使用FBV时,路由地址对应的是一个函数句柄,而在CBV中,路由地址对应的是视图类的 as_view 函数的执行结果。例如:

 from django.conf.urls import url
from app import views def test():
pass urlpatterns = [
url(r'^test_FBV/', test),
url(r'^test_CBV/', views.TestView.as_view()),
]

所以从这里就可以看出, as_view 函数的返回值一定也是一个函数句柄。查看as_view()函数源码:

 class View(object):

     @classonlymethod
def as_view(cls, **initkwargs):
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 update_wrapper(view, cls, updated=()) update_wrapper(view, cls.dispatch, assigned=())
return view

直接看 29 行, as_view 函数的返回值其实就是 15 行定义的 view 函数。也就是说当请求对应地址时,实际上执行的是这个 view 函数,

从 17 、 18 行可以看出,当我们在视图类中定义了 get 函数而没有定义 head 函数时,就定义一个 head 函数指向了 get 函数。也就是说当只定义了 get 函数而以 head 方式请求时,会执行 get 函数。

再看 22 行, view 函数的返回值其实是 dispatch 函数的执行结果,看源码:

 class View(object):
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
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)

我们会发现,dispatch方法很简单,就是判断当前请求方法名称是否包含在 http_method_names 这个列表中。如果包含,则通过 getattr 从当前视图类实例中获取该方法名称函数句柄赋值给 handler ,最后执行。也就是说如果请求方式为 put ,就会调用视图类中的 put 函数;如果请求方式为 patch ,就会调用视图类中的 patch 函数。

最新文章

  1. Xamarin.Android之ContentProvider
  2. javascript 使用方法名作为参数
  3. nginx php-fpm安装配置
  4. GBDT基本理论及利用GBDT组合特征的具体方法(收集的资料)
  5. Linux下的MySQL简单操作(服务启动与关闭、启动与关闭、查看版本)
  6. csu oj 1811: Tree Intersection (启发式合并)
  7. cocos2d-x生成随机数
  8. lightoj 1012
  9. python运维开发之第六天
  10. 10.8.5如何升级(app store 出错 请稍后重试 100)
  11. 初学者易上手的SSH-hibernate03 三大状态与缓存
  12. 报错信息 The jsp:param action must not be used outside the jsp:include, jsp:forward, or jsp:params elements 的原因及解决办法
  13. Bzoj3930: [CQOI 2015] 选数 & COGS2699: [CQOI 2015] 选数加强版
  14. Linux下编译GDAL
  15. asp.net core 系列 14 错误处理
  16. ElasticSearch(七):Java操作elasticsearch基于smartcn中文分词查询
  17. 优于 swagger 的 java markdown 文档自动生成框架-01-入门使用
  18. vim设置一个tab为4个空格,设置行号
  19. tcpdf开发文档(中文翻译版)
  20. Linux中利用extundelete恢复误删除的数据

热门文章

  1. Mina简单的入门示例
  2. Kafka基本架构及原理
  3. js 时间戳转时间工具类 js时间戳与时间互转
  4. DirectX using C++_error X3539:ps1_x is no longer supported...解决方案
  5. myeclipse中的项目 如何在项目视窗中显示setting,classpath等配置文件
  6. 【QT】文件读写操作
  7. Cesium高度解析
  8. 【Dubbo 源码解析】07_Dubbo 重试机制
  9. SQL查询无限层级结构的所有下级,所有上级
  10. Java编程常见缺陷汇总(一)