快速入门
开始我们的第一个Flask程序

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

把它保存为 hello.py ,然后用 Python 解释器来运行。注意: 确保你的应用文件名不是 flask.py ,因为这将与 Flask 本身冲突。

$ python hello.py
 * Running on http://127.0.0.1:5000/

现在访问 http://127.0.0.1:5000/ ,你会看见 Hello World 问候。

那么,这段代码做了什么?

  • 我们导入了 Flask 类,接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称。 如果你使用单一的模块(如本例),你应该使用 name 。这是必须的,这样 Flask 才知道到哪去找模板、静态文件等等。
  • 然后,我们使用 route() 装饰器告诉 Flask 什么样的URL 能触发我们的函数。这个函数返回我们想要显示在用户浏览器中的信息。
  • 最后我们用 run() 函数来让应用运行在本地服务器上。欲关闭服务器,按 Ctrl+C。

服务器设置

  1. 如果想要让外部可访问的该服务器该怎么办
    app.run(host=‘0.0.0.0’)这会让操作系统监听所有公网 IP。
  2. 调试模式
    如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生错误时提供一个相当有用的调试器。
    有两种途径来启用调试模式。一种是直接在应用对象上设置:
app.debug = True
app.run()
另一种是作为 run 方法的一个参数传入:

app.run(debug=True)
两种方法的效果完全相同。
  1. 路由
    如上所见, route() 装饰器把一个函数绑定到对应的 URL 上。
    这里是一些基本的例子:
@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World'
但是,不仅如此!你可以构造含有动态部分的 URL,也可以在一个函数上附着多个规则。

变量规则
要给 URL 添加变量部分,你可以把这些特殊的字段标记为 <variable_name> , 这个部分将会作为命名参数传递到你的函数。规则可以用 <converter:variable_name> 指定一个可选的转换器。这里有一些不错的例子:

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

转换器有下面几种:

int	接受整数
float	同 int ,但是接受浮点数
path	和默认的相似,但也接受斜线
唯一 URL / 重定向行为

Flask 的 URL 规则基于 Werkzeug 的路由模块。这个模块背后的思想是基于 Apache 以及更早的 HTTP 服务器主张的先例,保证优雅且唯一的 URL。
以这两个规则为例:

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

虽然它们看起来着实相似,但它们结尾斜线的使用在 URL 定义 中不同。 第一种情况中,指向 projects 的规范 URL 尾端有一个斜线。。访问一个结尾不带斜线的 URL 会被 Flask 重定向到带斜线的规范 URL 去,而,第二种情况的 URL 结尾不带斜线,类似 UNIX-like 系统下的文件的路径名。访问结尾带斜线的 URL 会产生一个 404 “Not Found” 错误。

  1. HTTP方法
    HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为。这里有一些例子:
from flask import Flask,request
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

如果存在 GET ,那么也会替你自动地添加 HEAD,无需干预。
常见的HTTP方法:

GET
浏览器告知服务器:只 获取 页面上的信息并发给我。这是最常用的方法。
HEAD
浏览器告诉服务器:欲获取信息,但是只关心 消息头 。应用应像处理 GET 请求一样来处理它,但是不分发实际内容。在 Flask 中你完全无需 人工 干预,底层的 Werkzeug 库已经替你打点好了。
POST
浏览器告诉服务器:想在 URL 上 发布 新信息。并且,服务器必须确保 数据已存储且仅存储一次。这是 HTML 表单通常发送数据到服务器的方法。
PUT
类似 POST 但是服务器可能触发了存储过程多次,多次覆盖掉旧值。你可 能会问这有什么用,当然这是有原因的。考虑到传输中连接可能会丢失,在 这种 情况下浏览器和服务器之间的系统可能安全地第二次接收请求,而 不破坏其它东西。因为 POST 它只触发一次,所以用 POST 是不可能的。
DELETE
删除给定位置的信息。
OPTIONS
给客户端提供一个敏捷的途径来弄清这个 URL 支持哪些 HTTP 方法。 从 Flask 0.6 开始,实现了自动处理。
有趣的是,在 HTML4 和 XHTML1 中,表单只能以 GET 和 POST 方法提交到服务器。但是 JavaScript 和未来的 HTML 标准允许你使用其它所有的方法。此外,HTTP 最近变得相当流行,浏览器不再是唯一的 HTTP 客户端。比如,许多版本控制系统就在使用 HTTP。

  1. 静态文件
    只要在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问
  2. 模板渲染
    Flask 配备了 Jinja2 模板引擎。使用 render_template() 方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。
这里有一个展示如何渲染模板的简例:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask 会在 templates 文件夹里寻找模板。所以,如果你的应用是个模块,这个文件夹应该与模块同级;如果它是一个包,那么这个文件夹作为包的子目录:

情况 1: 模块:
/application.py
/templates
    /hello.html
情况 2: 包:
/application
    /__init__.py
    /templates
        /hello.html
  1. 请求数据
    对于 Web 应用,与客户端发送给服务器的数据交互至关重要。在 Flask 中由全局的 request 对象来提供这些信息。
  2. 文件上传
    用 Flask 处理文件上传很简单。只要确保你没忘记在 HTML 表单中设置 enctype=“multipart/form-data” 属性,已上传的文件存储在内存或是文件系统中一个临时的位置。你可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法允许你把文件保存到服务器的文件系统上。这里是一个用它保存文件的例子:
from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')

如果你想知道上传前文件在客户端的文件名是什么,你可以访问 filename 属性。但请记住, 永远不要信任这个值,这个值是可以伪造的。如果你要把文件按客户端提供的文件名存储在服务器上,那么请把它传递给 Werkzeug 提供的 secure_filename() 函数:

from flask import request
from werkzeug import secure_filename

@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))

一些更好的例子,见 上传文件 模式。

  1. Cookies
    你可以通过 cookies 属性来访问 Cookies,用响应对象的 set_cookie 方法来设置 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() 函数然后再进行修改。

  1. 重定向和错误
    你可以用 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 。这告诉 Flask,该页的错误代码是 404 ,即没有找到。默认为 200,也就是一切正常。
  1. 关于响应
    视图函数的返回值会被自动转换为一个响应对象。如果返回的是一个合法的响应对象,它会从视图直接返回。如果返回的是一个字符串,响应对象会用字符串数据和默认参数创建。如果返回的是一个元组,且元组中的元素可以提供额外的信息。这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。如果上述条件均不满足, 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
  1. 会话
    除请求对象之外,还有一个 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'
这里提到的 escape() 可以在你模板引擎外做转义(如同本例)。

如何生成强壮的密钥
随机的问题在于很难判断什么是真随机。一个密钥应该足够随机。你的操作系统可以基于一个密钥随机生成器来生成漂亮的随机值,这个值可以用来做密钥:

>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
把这个值复制粘贴进你的代码中,你就有了密钥。

13.消息闪现
14. 日志记录
15.整合 WSGI 中间件