Flask基础-Part 2
本章完成以下内容:
- Session与Cookie
- 文件上传
- 日志
- 重定向和错误
- 配置信息
一、Session与Cookie
# 读取 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 属性来访问 Cookies,用响应对象的 set_cookie 方法来设置 Cookies。请求对象的 cookies 属性是一个内容为客户端提交的所有 Cookies 的字典。如果你想使用会话,请不要直接使用 Cookies,请参考 Session。
Session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名。这意味着用户可以查看你 Cookie 的内容,但却不能修改它,除非用户知道签名的密钥。要使用会话,你需要设置一个密钥。
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
@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 action="" 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'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
二、文件上传
用 Flask 处理文件上传很简单。只要确保你没忘记在 HTML 表单中设置 enctype=”multipart/form-data” 属性,已上传的文件存储在内存或是文件系统中一个临时的位置。你可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法允许你把文件保存到服务器的文件系统上。
import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
更简单解决方案
因为存在一个处理上传文件的范式,这个范式在大多数应用中机会不会有太大改变, 所以 Flask 存在一个扩展名为 Flask-Uploads ,这个扩展实现了一整套成熟的文件上传架构。它提供了包括文件类型白名单、黑名单等多种功能。
三、日志
从 Flask 0.3 开始,Flask 就已经预置了日志系统。
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
附带的 logger 是一个标准日志类 Logger ,所以更多信息请查阅 logging 的文档 。
四、重定向和错误
你可以用 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()
默认情况下,错误代码会显示一个黑白的错误页面。如果你要定制错误页面, 可以使用 errorhandler() 装饰器:
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
如果你想在视图里操纵上述步骤结果的响应对象,可以使用 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
五、配置信息
Flask 被设计为需要配置来启动应用。你可以在代码中硬编码配置,这对于小的应用并不坏,但是有更好的方法。跟你如何载入配置无关,会有一个可用的配置对象保存着载入的配置值: Flask 对象的 config 属性。这是 Flask 自己放置特定配置值的地方,也是扩展可以存储配置值的地方。但是,你也可以把自己的配置保存到这个对象里。
config 实际上继承于字典,并且可以像修改字典一样修改它:
app = Flask(__name__)
app.config['DEBUG'] = True
给定的配置值会被推送到 Flask 对象中,所以你可以在那里读写它们:app.debug = True
你可以使用 dict.update() 方法来一次性更新多个键:
app.config.update(
DEBUG=True,
SECRET_KEY='...'
)
从文件配置
如果你能在独立的文件里存储配置,理想情况是存储在当前应用包之外,它将变得更有用。
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
首先从 yourapplication.default_settings 模块加载配置,然后用 YOURAPPLICATION_SETTINGS 环境变量指向的文件的内容覆盖其值。
配置文件其实是 Python 文件。只有大写名称的值才会被存储到配置对象中。所以请确保你在配置键中使用了大写字母。
# Example configuration
DEBUG = False
SECRET_KEY = '?\xbf,\xb4\x8d\xa3"<\x9c\xb0@\x0f5\xab,w\xee\x8d$0\x13\x8b83'