Flask 快速上手文档4

Cookies

要访问 cookies ,可以使用 cookies 属性。可以使用响应 对象 的 set_cookie 方法来设置 cookies 。请求对象的 cookies 属性是一个包含了客户端传输的所有 cookies 的字典。在 Flask 中,如果使用 会话 ,那么就不要直接使用 cookies ,因为 会话 比较安全一些。

读取 cookies:

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

储存 cookies:

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

注意, cookies 设置在响应对象上。通常只是从视图函数返回字符串, Flask 会把它们 转换为响应对象。如果你想显式地转换,那么可以使用 make_response() 函数,然后再修改它。

使用 延迟的请求回调 方案可以在没有响应对象的情况下设置一个 cookie 。

同时可以参见 关于响应 。

重定向和错误

使用 redirect() 函数可以重定向。使用 abort() 可以 更早退出请求,并返回错误代码:

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401 表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。

缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler() 装饰器可以定制出错页面:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

注意 render_template() 后面的 404 ,这表示页面对就的出错 代码是 404 ,即页面不存在。缺省情况下 200 表示:一切正常。

详见 错误处理 。

关于响应

视图函数的返回值会自动转换为一个响应对象。如果返回值是一个字符串,那么会被 转换为一个包含作为响应体的字符串、一个 200 OK 出错代码 和一个 text/html 类型的响应对象。如果返回值是一个字典,那么会调用 jsonify() 来产生一个响应。以下是转换的规则:

  1. 如果视图返回的是一个响应对象,那么就直接返回它。

  2. 如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的 响应对象。

  3. 如果返回的是一个字典,那么调用 jsonify 创建一个响应对象。

  4. 如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项目,且项目应当由 (response, status) 、 (response, headers) 或者 (response, status, headers) 组成。 status 的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典。

  5. 如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。

如果想要在视图内部掌控响应对象的结果,那么可以使用 make_response() 函数。

设想有如下视图:

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

可以使用 make_response() 包裹返回表达式,获得响应对象,并对该对象 进行修改,然后再返回:

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

JSON 格式的 API

JSON 格式的响应是常见的,用 Flask 写这样的 API 是很容易上手的。如果从视图 返回一个 dict ,那么它会被转换为一个 JSON 响应。

@app.route("/me")
def me_api():
    user = get_current_user()
    return {
        "username": user.username,
        "theme": user.theme,
        "image": url_for("user_image", filename=user.image),
    }

如果 dict 还不能满足需求,还需要创建其他类型的 JSON 格式响应,可以使用 jsonify() 函数。该函数会序列化任何支持的 JSON 数据类型。 也可以研究研究 Flask 社区扩展,以支持更复杂的应用。

@app.route("/users")
def users_api():
    users = get_all_users()
    return jsonify([user.to_json() for user in users])

会话

除了请求对象之外还有一种称为 session 的对象,允许你在不同请求 之间储存信息。这个对象相当于用密钥签名加密的 cookie ,即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它。

使用会话之前你必须设置一个密钥。举例说明:

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

这里用到的 escape() 是用来转义的。如果不使用模板引擎就可以像上例 一样使用这个函数来转义。

如何生成一个好的密钥

生成随机数的关键在于一个好的随机种子,因此一个好的密钥应当有足够的随机性。 操作系统可以有多种方式基于密码随机生成器来生成随机数据。使用下面的命令 可以快捷的为 Flask.secret_key ( 或者 SECRET_KEY )生成值:

$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'

基于 cookie 的会话的说明: Flask 会取出会话对象中的值,把值序列化后储存到 cookie 中。在打开 cookie 的情况下,如果需要查找某个值,但是这个值在请求中 没有持续储存的话,那么不会得到一个清晰的出错信息。请检查页面响应中的 cookie 的大小是否与网络浏览器所支持的大小一致。

除了缺省的客户端会话之外,还有许多 Flask 扩展支持服务端会话。

消息闪现

一个好的应用和用户接口都有良好的反馈,否则到后来用户就会讨厌这个应用。 Flask 通过闪现系统来提供了一个易用的反馈方式。闪现系统的基本工作原理是在请求结束时 记录一个消息,提供且只提供给下一个请求使用。通常通过一个布局模板来展现闪现的 消息。

flash() 用于闪现一个消息。在模板中,使用 get_flashed_messages() 来操作消息。完整的例子参见 消息闪现 。

日志

Changelog

有时候可能会遇到数据出错需要纠正的情况。例如因为用户篡改了数据或客户端代码出错 而导致一个客户端代码向服务器发送了明显错误的 HTTP 请求。多数时候在类似情况下 返回 400 Bad Request 就没事了,但也有不会返回的时候,而代码还得继续运行 下去。

这时候就需要使用日志来记录这些不正常的东西了。自从 Flask 0.3 后就已经为你配置好 了一个日志工具。

以下是一些日志调用示例:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

logger 是一个标准的 Logger Logger 类, 更多信息详见官方的 logging 文档。

更多内容请参阅 应用错误处理 。

集成 WSGI 中间件

如果想要在应用中添加一个 WSGI 中间件,那么可以包装内部的 WSGI 应用。假设为了 解决 lighttpd 的错误,你要使用一个来自 Werkzeug 包的中间件,那么可以这样做:

from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

使用 Flask 扩展

扩展是帮助完成公共任务的包。例如 Flask-SQLAlchemy 为在 Flask 中轻松使用 SQLAlchemy 提供支持。

发布了134 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/keny88888/article/details/104007906