Django中CBV源码解析
2024-10-14 21:44:05
使用
关于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 函数。
最新文章
- Xamarin.Android之ContentProvider
- javascript 使用方法名作为参数
- nginx php-fpm安装配置
- GBDT基本理论及利用GBDT组合特征的具体方法(收集的资料)
- Linux下的MySQL简单操作(服务启动与关闭、启动与关闭、查看版本)
- csu oj 1811: Tree Intersection (启发式合并)
- cocos2d-x生成随机数
- lightoj 1012
- python运维开发之第六天
- 10.8.5如何升级(app store 出错 请稍后重试 100)
- 初学者易上手的SSH-hibernate03 三大状态与缓存
- 报错信息 The jsp:param action must not be used outside the jsp:include, jsp:forward, or jsp:params elements 的原因及解决办法
- Bzoj3930: [CQOI 2015] 选数 &; COGS2699: [CQOI 2015] 选数加强版
- Linux下编译GDAL
- asp.net core 系列 14 错误处理
- ElasticSearch(七):Java操作elasticsearch基于smartcn中文分词查询
- 优于 swagger 的 java markdown 文档自动生成框架-01-入门使用
- vim设置一个tab为4个空格,设置行号
- tcpdf开发文档(中文翻译版)
- Linux中利用extundelete恢复误删除的数据
热门文章
- Mina简单的入门示例
- Kafka基本架构及原理
- js 时间戳转时间工具类 js时间戳与时间互转
- DirectX using C++_error X3539:ps1_x is no longer supported...解决方案
- myeclipse中的项目 如何在项目视窗中显示setting,classpath等配置文件
- 【QT】文件读写操作
- Cesium高度解析
- 【Dubbo 源码解析】07_Dubbo 重试机制
- SQL查询无限层级结构的所有下级,所有上级
- Java编程常见缺陷汇总(一)