### 导航
- [索引](# "总目录")
- [下一页](# "使用 WTForms 进行表单验证") |
- [上一页](# "缓存") |
- [Flask 0.10.1 文档](#) »
- [Flask 代码模式](#) »
# 视图装饰器
Python 拥有一件非常有趣的特性,那就是函数装饰器。这个特性允许您使用一些非常简介的语法编辑 Web 应用。因为 Flask 中的每个视图都是一个函数装饰器,这些装饰器被用来将附加的功能注入到一个或者多个函数中。 [route()](# "flask.Flask.route")装饰器您可能已经使用过了。但是在一些情况下您需要实现自己的装饰器。例如,您有一个仅供登陆后的用户访问的视图,如果未登录的用户试图访问,则把用户转接到登陆界面。这个例子很好地说明了装饰器的用武之地。
### 过滤未登录用户的装饰器
现在让我们实现一个这样的装饰器。装饰器是指返回函数的函数,它其实非常简单。您仅需要记住,当实现一个类似的东西,其实是更新 __name__ 、 __module__以及函数的其他一些属性,这件事情经常被遗忘。但是您不必亲自动手,这里有一个专门用于处理这些的以装饰器形式调用的函数([functools.wraps()](http://docs.python.org/dev/library/functools.html#functools.wraps "(在 Python v3.5)") [http://docs.python.org/dev/library/functools.html#functools.wraps] )。
这个例子家丁登陆页面的名字是 'login' 并且当前用户被保存在 g.user 当中,如果么有用户登陆, g.user 会是 None:
~~~
from functools import wraps
from flask import g, request, redirect, url_for
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function
~~~
所以您怎么使用这些装饰器呢?将它加为视图函数外最里层的装饰器。当添加更多装饰器的话,一定要记住 [route()](# "flask.Flask.route") 考试最外面的:
~~~
@app.route('/secret_page')
@login_required
def secret_page():
pass
~~~
### 缓存装饰器
试想你有一个运算量很大的函数,而且您希望能够将生成的结果在一段时间内缓存起来,一个装饰器将会非常适合用于干这种事。我们假定您已经参考 [*缓存*](#)中提到的内容配置好了缓存功能。
这里有一个用作例子的缓存函数,它从一个指定的前缀(通常是一个格式化字符串)和当前请求的路径生成一个缓存键。请注意我们创建了一个这样的函数: 它先创建一个装饰器,然后用这个装饰器包装目标函数。听起来很复杂?不幸的是,这的确有些难,但是代码看起来会非常直接明了。
被装饰器包装的函数将能做到如下几点:
1. 以当前请求和路径为基础生成缓存时使用的键。
1. 从缓存中取出对应键的值,如果缓存返回的不是空,我们就将它返回回去。
1. 如果缓存中没有这个键,那么最初的函数将会被执行,并且返回的值在指定时间(默认5分钟内)被缓存起来。
代码如下:
~~~
from functools import wraps
from flask import request
def cached(timeout=5 * 60, key='view/%s'):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator
~~~
注意,这段代码假定一个示例用的 cache 对象时可用的。请参考 [*缓存*](#)以获取更多信息。
### 模板装饰器
TurboGears 的家伙们前一段时间发明了一种新的常用范式,那就是模板装饰器。这个装饰器的关键在于,您将想要传递给模板的值组织成字典的形式,然后从视图函数中返回,这个模板将会被自动渲染。这样,下面的三个例子就是等价的了:
~~~
@app.route('/')
def index():
return render_template('index.html', value=42)
@app.route('/')
@templated('index.html')
def index():
return dict(value=42)
@app.route('/')
@templated()
def index():
return dict(value=42)
~~~
正如您所看到的,如果没有模板名被指定,那么他会使用 URL 映射的最后一部分,然后将点转换为反斜杠,最后添加上 '.html' 作为模板的名字。当装饰器包装的函数返回,返回的字典就会被传递给模板渲染函数。如果 None 被返回了,那么相当于一个空的字典。如果非字典类型的对象被返回,函数将照原样将那个对象再次返回。这样您就可以继续使用重定向函数或者返回简单的字符串了。
这是那个装饰器的源代码:
~~~
from functools import wraps
from flask import request
def templated(template=None):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
template_name = template
if template_name is None:
template_name = request.endpoint \
.replace('.', '/') + '.html'
ctx = f(*args, **kwargs)
if ctx is None:
ctx = {}
elif not isinstance(ctx, dict):
return ctx
return render_template(template_name, **ctx)
return decorated_function
return decorator
~~~
### 终端装饰器
如果您希望使用 werkzeug 路由系统来获得更多的灵活性。您需要将终点(Endpoint)像 [Rule](http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.Rule "(在 Werkzeug v0.10)") [http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.Rule] 中定义的那样映射起来。通过一个装饰器是可以做到的,例如:
~~~
from flask import Flask
from werkzeug.routing import Rule
app = Flask(__name__)
app.url_map.add(Rule('/', endpoint='index'))
@app.endpoint('index')
def my_index():
return "Hello world"
~~~
© 版权所有 2013, Armin Ronacher.
- 欢迎使用 Flask
- 前言
- 给有经验程序员的前言
- 安装
- 快速入门
- 教程
- 介绍 Flaskr
- 步骤 0: 创建文件夹
- 步骤 1: 数据库模式
- 步骤 2: 应用设置代码
- 步骤 3: 创建数据库
- 步骤 4: 请求数据库连接
- 步骤 5: 视图函数
- 步骤 6: 模板
- 步骤 7: 添加样式
- 福利: 应用测试
- 模板
- 测试 Flask 应用
- 记录应用错误
- 配置处理
- 信号
- 即插视图
- 应用上下文
- 请求上下文
- 用蓝图实现模块化的应用
- Flask 扩展
- 与 Shell 共舞
- Flask 代码模式
- 大型应用
- 应用程序的工厂函数
- 应用调度
- 使用 URL 处理器
- 部署和分发
- 使用 Fabric 部署
- 在 Flask 中使用 SQLite 3
- 在 Flask 中使用 SQLAlchemy
- 上传文件
- 缓存
- 视图装饰器
- 使用 WTForms 进行表单验证
- 模板继承
- 消息闪现
- 用 jQuery 实现 Ajax
- 自定义错误页面
- 延迟加载视图
- 在 Flask 中使用 MongoKit
- 添加 Favicon
- 数据流
- 延迟请求回调
- 添加 HTTP Method Overrides
- 请求内容校验码
- 基于 Celery 的后台任务
- 部署选择
- mod_wsgi (Apache)
- 独立 WSGI 容器
- uWSGI
- FastCGI
- CGI
- 聚沙成塔
- API
- JSON 支持
- Flask 中的设计决策
- HTML/XHTML 常见问题
- 安全注意事项
- Flask 中的 Unicode
- Flask 扩展开发
- Pocoo 风格指引
- Python 3 支持
- 升级到最新版本
- Flask Changelog
- 许可证
- 术语表