本篇介绍Django 的MTV结构中的 View。
通过这篇文章,你能了解到:
- view是什么?
- 定义视图的两种方式
- 给视图加装饰器,来增加额外的功能
View
一个视图函数(或视图类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py
的文件中。
FBV与CBV
FBV
function based view 基于函数的视图
定义FBV:
1 | def AddPublisher(request): |
对应关系:
1 | url(r'^publisher_add/', views.AddPublisher), |
CBV
class based view 基于类的视图
定义 CBV:
- 较于FBV会更清晰
1 | from django.views import View |
- 修改对应关系,执行as_view()方法
1 | url(r'^publisher_add/', views.AddPublisher.as_view()), |
源码剖析
项目启动时,运行 urls.py ;as_view方法去执行,返回view函数
请求到来时,执行view函数
实例化AddPublisher —> self
self.request = request
执行view函数中的 self.dispatch(request, args, *kwargs) 方法
判断请求方式是否被允许
if request.method.lower() in self.http_method_names:
允许
list中有这个方法,且在自定义的类中也写了这个方法。
通过反射获取请求方式对应的方法 —> handler (重要)
不允许
list中没有该方法
handler = self.http_method_not_allowed
—> handler
执行handler,获取响应
允许
不允许
执行
http_method_not_allowed
,返回一个HttpResponse
最终目标就是将我们自定义的类中的 get 或 post 方法返回!
1 | def view(request, *args, **kwargs): |
dispatch
1 | def dispatch(self, request, *args, **kwargs): |
handler
1 | def http_method_not_allowed(self, request, *args, **kwargs): |
给视图加装饰器
装饰器是在不修改源代码以及调用方式的情况下,增加新的功能。
定义装饰器
这里定义一个计算执行时间的装饰器
1 | from functools import wraps |
note:对于inner函数,我们需要使用 wraps 装饰器装饰,这样可以把被装饰函数的配置信息(__name__
, __doc__
)等与inner函数的配置信息进行替换。
添加装饰器的几种方式
由于视图分为FBV与CBV,对于FBV,可以给它直接加装饰器,对于CBV的绑定方法,有下列几种情况
直接加(不建议)
1 |
|
在方法的定义上使用 method_decorator
装饰
通过 method_decorator
可以把函数装饰器转为方法装饰器
1 | from django.utils.decorators import method_decorator |
在类的定义上使用 method_decorator
装饰
1 |
|
批量添加
对于前面这些,都是单独给一个函数或方法来加装饰器,那如果批量添加该怎么做呢?
通过前面对源码的剖析,在 dispatch
方法中,它按照请求方式的不同返回不同的方法,所以我们可以给 dispatch
方法加上装饰器,从而达到给这些方法加上装饰器的目的。
给父类的 dispatch
加装饰器 (推荐)
- 当子类没有
dispatch
方法的时候,会调用父类的dispatch
方法,这样把装饰器加到了父类的dispatch
上达到批量添加的目的。
1 |
|
子类重写 dispatch
(不推荐)
1 |
|
加不加 method_decorator 的区别
@timer直接装饰方法的话:把这个方法当作一个函数, args内的第一个参数是self,第二个参数是request对象
加上 method_decorator 把它当作绑定方法,args内的第一个参数是request对象
它们功能上没有不同,但是就参数的位置上来说是不同的。只要可以确定request对象的位置,正确使用就行。
小结
当了解了view之后,还需要对参数request对象和返回值response对象做一个了解,下一篇为 Django的request与response。