视图装饰器

    让我们来实现这个装饰器。装饰器是一个包装并替换另一个函数的函数。既然源函数已经被替代,就需要记住:要复制源函数的信息到新函数中。可以用functools.wraps() 处理这个事情。

    下面是检查登录装饰器的例子。假设登录页面为 'login' ,当前用户被储存在g.user 中,如果还没有登录,其值为 None:

    为了使用这个装饰器呢,需要把这个装饰器放在最靠近函数的地方。当使用更进一步的装饰器时,请记住要把 装饰器放在最外面:

    1. @app.route('/secret_page')
    2. @login_required
    3. def secret_page():
    4. pass

    Note

    登录页面在一个GET 请求之后 next 值会存在于 request.args之中。当从登录表单发送 POST 请求时必须一起传递它。可以使用一个隐藏标记来做到这点,然后当用户登录时,从 request.form 获取它。

    下面是一个示例缓存函数。它根据一个特定的前缀(实际上是一个格式字符串)和请求的当前路径生成缓存键。注意,我们先使用了一个函数来创建装饰器,这个装饰器用于装饰函数。听起来拗口吧,确实有一点复杂,但是下面的示例代码还是很容易读懂的。

    被装饰代码按如下步骤工作

    • 基于基础路径获得当前请求的唯一缓存键。

    • 从缓存中获取键值。如果获取成功则返回获取到的值。

    • 否则调用原来的函数,并把返回值存放在缓存中,直至过期(缺省值为五分钟)。

    1. from functools import wraps
    2. from flask import request
    3. def decorator(f):
    4. @wraps(f)
    5. def decorated_function(*args, **kwargs):
    6. cache_key = key % request.path
    7. rv = cache.get(cache_key)
    8. if rv is not None:
    9. return rv
    10. rv = f(*args, **kwargs)
    11. cache.set(cache_key, rv, timeout=timeout)
    12. return rv
    13. return decorated_function
    14. return decorator

    注意,以上代码假设存在一个可用的实例化的 cache 对象,更多信息参见缓存 方案。

    不久前, TurboGear 的人发明了模板装饰器这个通用模式。其工作原理是返回一个字典,这个字典包含从视图传递给模板的值,模板自动被渲染。以下三个例子的功能是相同的:

    正如你所见,如果没有提供模板名称,那么就会使用 URL 映射的端点(把点转换为斜杠)加上 '.html' 。如果提供了,那么就会使用所提供的模板名称。当装饰器函数返回时,返回的字典就被传送到模板渲染函数。如果返回的是 None ,就会使用空字典。如果返回的不是字典,那么就会直接传递原封不动的返回值。这样就可以仍然使用重定向函数或返回简单的字符串。

    以下是装饰器的代码:

    1. from functools import wraps
    2. from flask import request, render_template
    3. def templated(template=None):
    4. def decorator(f):
    5. @wraps(f)
    6. def decorated_function(*args, **kwargs):
    7. template_name = template
    8. if template_name is None:
    9. template_name = request.endpoint \
    10. .replace('.', '/') + '.html'
    11. ctx = f(*args, **kwargs)
    12. if ctx is None:
    13. ctx = {}
    14. elif not isinstance(ctx, dict):
    15. return ctx
    16. return render_template(template_name, **ctx)
    17. return decorator

    当你想要使用 werkzeug 路由系统,以便于获得更强的灵活性时,需要和 中定义的一样,把端点映射到视图函数。这样就需要用的装饰器了。例如: