《Flask 入门教程》 第 2 章:Hello, Flask!

追溯到最初,Flask 诞生于 Armin Ronacher 在 2010 年愚人节开的一个玩笑。后来,它逐渐发展成为一个成熟的 Python Web 框架,愈来愈受到开发者的喜好。目前它在 GitHub 上是 Star 数量最多的 Python Web 框架,没有之一。python

Flask 是典型的微框架,做为 Web 框架来讲,它仅保留了核心功能:请求响应处理模板渲染。这两类功能分别由 Werkzeug(WSGI 工具库)完成和 Jinja(模板渲染库)完成,由于 Flask 包装了这两个依赖,咱们暂时不用深刻了解它们。git

主页

这一章的主要任务就是为咱们的程序编写一个简单的主页。主页的 URL 通常就是根地址,即 /。当用户访问根地址的时候,咱们须要返回一行欢迎文字。这个任务只须要下面几行代码就能够完成:github

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Welcome to My Watchlist!'复制代码

按照惯例,咱们把程序保存为 app.py,确保当前目录是项目的根目录,而后在命令行窗口执行 flask run 命令启动程序(按下 Control + C 能够退出):django

$ flask run
* Serving Flask app "app.py"
* Environment: production
  WARNING: Do not use the development server in a production environment.
  Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)复制代码

如今打开浏览器,访问 http://localhost:5000 便可访问咱们的程序主页,并看到咱们在程序里返回的问候语,以下图所示:flask



执行 flask run 命令时,Flask 会使用内置的开发服务器来运行程序。这个服务器默认监听本地机的 5000 端口,也就是说,咱们能够经过在地址栏输入 http://127.0.0.1:5000 或是 http://localhost:5000 访问程序。浏览器

注意 内置的开发服务器只能用于开发时使用,部署上线的时候要换用性能更好的服务器,咱们会在最后一章学习。服务器

解剖时间

下面咱们来分解这个 Flask 程序,了解它的基本构成。app

首先咱们从 flask 包导入 Flask 类,经过实例化这个类,建立一个程序对象 app框架

from flask import Flask
app = Flask(__name__)复制代码

接下来,咱们要注册一个处理函数,这个函数是处理某个请求的处理函数,Flask 官方把它叫作视图函数(view funciton),你能够理解为“请求处理函数”。编辑器

所谓的“注册”,就是给这个函数戴上一个装饰器帽子。咱们使用 app.route() 装饰器来为这个函数绑定对应的 URL,当用户在浏览器访问这个 URL 的时候,就会触发这个函数,获取返回值,并把返回值显示到浏览器窗口:

@app.route('/')
def hello():
    return 'Welcome to My Watchlist!'复制代码

填入 app.route() 装饰器的第一个参数是 URL 规则字符串,这里的 /指的是根地址。

咱们只须要写出相对地址,主机地址、端口号等都不须要写出。因此说,这里的 / 对应的是主机名后面的路径部分,完整 URL 就是 http://localhost:5000/。若是咱们这里定义的 URL 规则是 /hello,那么完整 URL 就是 http://localhost:5000/hello

整个请求的处理过程以下所示:

  1. 当用户在浏览器地址栏访问这个地址,在这里即 http://localhost:5000/
  2. 服务器解析请求,发现请求 URL 匹配的 URL 规则是 /,所以调用对应的处理函数 hello()
  3. 获取 hello() 函数的返回值,处理后返回给客户端(浏览器)
  4. 浏览器接受响应,将其显示在窗口上

提示 在 Web 程序的语境下,虽然客户端可能有多种类型,但在本书里一般是指浏览器。

程序发现机制

若是你把上面的程序保存成其余的名字,好比 hello.py,接着执行 flask run 命令会返回一个错误提示。这是由于 Flask 默认会假设你把程序存储在名为 app.py 或 wsgi.py 的文件中。若是你使用了其余名称,就要设置系统环境变量 FLASK_APP 来告诉 Flask 你要启动哪一个程序。

Flask 经过读取这个文件对应的模块寻找要运行的程序实例,你能够把它设置成下面这些值:

  • 模块名
  • Python 导入路径
  • 文件目录路径

管理环境变量

如今在启动 Flask 程序的时候,咱们一般要和两个环境变量打交道:FLASK_APPFLASK_ENV。由于咱们的程序如今的名字是 app.py,暂时不须要设置 FLASK_APPFLASK_ENV 用来设置程序运行的环境,默认为 production。在开发时,咱们须要开启调试模式(debug mode)。调试模式能够经过将系统环境变量 FLASK_ENV 设为 development 来开启。调试模式开启后,当程序出错,浏览器页面上会显示错误信息;代码出现变更后,程序会自动重载。

为了避免用每次打开新的终端会话都要设置环境变量,咱们安装用来管理系统环境变量的 python-dotenv:

$ pipenv install python-dotenv复制代码

当 python-dotenv 安装后,Flask 会从项目根目录的 .flaskenv 和 .env 文件读取环境变量并设置。咱们分别使用文本编辑器建立这两个文件,或是使用更方便的 touch 命令建立:

$ touch .env .flaskenv复制代码

.flaskenv 用来存储 Flask 命令行系统相关的公开环境变量;而 .env 则用来存储敏感数据,不该该提交进Git仓库,咱们把 .env 添加到 .gitignore 文件的结尾(新建一行)来让 Git 忽略它。你可使用编辑器执行这个操做:

.env复制代码

在新建立的 .flaskenv 文件里,咱们写入一行 FLASK_ENV=development ,将环境变量 FLASK_ENV 的值设为 development,以便开启调试模式:

FLASK_ENV=development复制代码

实验时间

在这个小节,咱们能够经过作一些实验,来扩展和加深对本节内容的理解。

修改视图函数返回值

首先,你能够自由修改视图函数的返回值,好比:

@app.route('/')
def hello():
    return u'欢迎来到个人 Watchlist!'复制代码

返回值做为响应的主体,默认会被浏览器做为 HTML 格式解析,因此咱们能够添加一个 HTML 元素标记:

@app.route('/')
def hello():
    return '<h1>Hello Totoro!</h1><img src="http://helloflask.com/totoro.gif">'复制代码

保存修改后,只须要在浏览器里刷新页面,你就会看到页面上的内容也会随之变化。



修改 URL 规则

另外,你也能够自由修改传入 app.route 装饰器里的 URL 规则字符串,但要注意以斜线 / 做为开头。好比:

@app.route('/home')
def hello():
    return 'Welcome to My Watchlist!'复制代码

保存修改,这时刷新浏览器,则会看到一个 404 错误提示,提示页面未找到(Page Not Found)。这是由于视图函数的 URL 改为了 /home,而咱们刷新后访问的地址仍然是旧的 /。若是咱们把访问地址改为 http://localhost:5000/home,就会正确看到返回值。

一个视图函数也能够绑定多个 URL,这经过附加多个装饰器实现,好比:

@app.route('/')
@app.route('/index')
@app.route('/home')
def hello():
    return 'Welcome to My Watchlist!'复制代码

如今不管是访问 http://localhost:5000/、http://localhost:5000/home 仍是 http://localhost:5000/index 均可以看到返回值。

在前面,咱们之因此把传入 app.route 装饰器的参数称为 URL 规则,是由于咱们也能够在 URL 里定义变量部分。好比下面这个视图函数会处理全部相似 /user/<name> 的请求:

@app.route('/user/<name>')
def user_page():
    return 'User page'复制代码

不论你访问 http://localhost:5000/user/greyli,仍是 http://localhost:5000/user/peter,抑或是 http://localhost:5000/user/甲,都会触发这个函数。经过下面的方式,咱们也能够在视图函数里获取到这个变量值:

@app.route('/user/<name>')
def user_page(name):
    return 'User: %s' % name复制代码

修改视图函数名?

最后一个能够修改的部分就是视图函数的名称了。首先,视图函数的名字是自由定义的,和 URL 规则无关。和定义其余函数或变量同样,只须要让它表达出所要处理页面的含义便可。

除此以外,它还有一个重要的做用:做为表明某个路由的端点(endpoint),同时用来生成 URL。对于程序内的 URL,为了不手写,Flask 提供了一个 url_for 函数来生成 URL,它接受的第一个参数就是端点值,默认为视图函数的名称:

from flask import url_for

...

@app.route('/')
def hello():
    return 'Hello'

@app.route('/user/<name>')
def user_page(name):
    return 'User: %s' % name

@app.route('/test')
def test_url_for():
    # 下面是一些调用示例:
    print(url_for('hello'))  # 输出:/
    # 注意下面两个调用是如何生成包含 URL 变量的 URL 的
    print(url_for('user_page', name='greyli'))  # 输出:/user/greyli
    print(url_for('user_page', name='peter'))  # 输出:/user/peter
    print(url_for('test_url_for'))  # 输出:/test
    # 下面这个调用传入了多余的关键字参数,它们会被做为查询字符串附加到 URL 后面。
    print(url_for('test_url_for', num=2))  # 输出:/test?num=2
    return 'Test page'复制代码

实验过程当中编写的代码能够删掉,也能够保留,但记得为根地址返回一行问候,这但是咱们这一章的任务。

本章小结

这一章咱们为程序编写了主页,同时学习了 Flask 视图函数的基本编写方式。结束前,让咱们提交代码:

$ git add .
$ git commit -m "Add minimal home page"
$ git push复制代码

为了保持简单,咱们统一在章节最后一次提交全部改动。在现实世界里,一般会根据须要分为多个 commit;一样的,这里使用 -m 参数给出简单的提交信息。在现实世界里,你可能须要撰写更完整的提交信息。

提示 你能够在 GitHub 上查看本书示例程序的对应 commit:016302a

进阶提示

  • 若是你使用 Python 2.7,为了使程序正常工做,须要在脚本首行添加编码声明 # -*- coding: utf-8-*- ,并在包含中文的字符串前面添加 u 前缀。本书中对于包含中文的字符串均添加了 u 前缀,这在 Python 3 中并不须要。
  • 对于 URL 变量,Flask 还支持在 URL 规则字符串里对变量设置处理器,对变量进行预处理。好比 /user/<int:number> 会将 URL 中的 number 部分处理成整型,同时这个变量值接收传入数字。
  • 由于 Flask 的上下文机制,有一些变量和函数(好比 url_for函数)只能在特定的状况下才能正确执行,好比视图函数内。咱们先暂时不用纠结,后面再慢慢了解。
  • 名字以 . 开头的文件默认会被隐藏,执行 ls 命令时会看不到它们,这时你可使用 ls -f 命令来列出全部文件。
  • 了解 HTTP 基本知识将会有助于你了解 Flask 的工做原理。
  • 阅读文章《互联网是如何工做的》
  • 阅读文章《从HTTP请求 - 响应循环探索Flask的基本工做方式》
  • 若是你是《Flask Web 开发实战》的读者,这部分的进阶内容能够在第 1 章《初识 Flask》和第 2 章《HTTP 和 Flask》找到。
相关文章
相关标签/搜索