02.flask应用基本结构
配套视频教程
- 初始化
所有的Flask程序都必须创建一个程序实例, 这个程序实例就是Flask类的对象。客户端把请求发送给Web服务器, 服务器再把请求发送给Flask程序实例, 然后由程序实例处理请求。
创建程序实例:
from flask import Flask
app = Flask(__name__)
此处的__name__
是一个全局变量, 它的值是代码所处的模块或包的名字, Flask用这个参数决定程序的根目录, 以便稍后能找到相对于程序根目录的资源文件位置。
2.路由和视图函数
客户端把请求发送给Web服务器, 服务器再把请求发送给Flask程序实例, 然后由Flask程序实例处理请求。
程序实例如何处理请求, 答案是程序实例通过路由来处理请求——路由就是URL和处理请求的函数的映射——处理请求的函数就叫做视图函数。
Flask定义路由最简便的方式, 是使用程序实例提供的app.route修饰器:
@app.route('/'):
def index():
return '<h1>Hello world!<h1>'
前例把index()函数注册为程序根地址的处理程序。 ( 如果部署程序的服务器域名为www.example.com, 在浏览器中访问http://www.example.com后, 会触发服务器执行index()函数。 )
这个函数的返回值称为响应, 是客户端接收到的内容。
地址中包含可变部分的路由:
@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' %name
尖括号中的内容就是动态部分,任何能匹配静态部分的URL都会映射到这个视图函数, 调用视图函数时, Flask会将动态部分作为参数传入函数。
注意:路由中的动态部分默认类型是字符串, 不过也可以使用别的类型如:/user/<int: id>只会匹配动态片段id为整数的url。
3.启动服务器
Flask 应用自带 Web 开发服务器,通过 flask run 命令启动。这个命令在 FLASK_APP 环境变量指定的 Python 脚本中寻找应用实例。
Linux 和 macOS 用户执行下述命令启动 Web 服务器:
(venv) $ export FLASK_APP=app.py
(venv) $ flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
微软 Windows 用户执行的命令和刚才一样,只不过设定 FLASK_APP 环境变量的方式不同:
(venv) $ set FLASK_APP=app.py
(venv) $ flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
服务器启动后便开始轮询,处理请求。直到按 Ctrl+C 键停止服务器,轮询才会停止。
服务器运行时,在 Web 浏览器的地址栏中输入 http://localhost:5000/。你看到的页面如图 2-1 所示。
Flask Web 开发服务器也可以通过编程的方式启动:调用 app.run() 方法。
if __name__ == '__main__':
app.run(debug=True) #debug参数为True, 表示启用调试模式。
命令行选项
flask 命令支持一些选项。执行 flask --help,或者执行 flask 而不提供任何参数,可以查看哪些选项可用:
(venv) $ flask --help
Usage: flask [OPTIONS] COMMAND [ARGS]...
This shell command acts as general utility script for Flask applications.
It loads the application configured (through the FLASK_APP environment
variable) and then provides commands either provided by the application or
Flask itself.
The most useful commands are the "run" and "shell" command.
Example usage:
$ export FLASK_APP=hello.py
$ export FLASK_DEBUG=1
$ flask run
Options:
--version Show the flask version
--help Show this message and exit.
Commands:
run Runs a development server.
shell Runs a shell in the app context.
flask shell 命令在应用的上下文中打开一个 Python shell 会话。在这个会话中可以运行维护任务或测试,也可以调试问题。几章之后将举例说明这个命令的用途。
flask run 命令我们已经用过,从名称可以看出,它的作用是在 Web 开发服务器中运行应用。这个命令有多个参数:
(venv) $ flask run --help
Usage: flask run [OPTIONS]
Runs a local development server for the Flask application.
This local server is recommended for development purposes only but it can
also be used for simple intranet deployments. By default it will not
support any sort of concurrency at all to simplify debugging. This can be
changed with the --with-threads option which will enable basic
multithreading.
The reloader and debugger are by default enabled if the debug flag of
Flask is enabled and disabled otherwise.
Options:
-h, --host TEXT The interface to bind to.
-p, --port INTEGER The port to bind to.
--reload / --no-reload Enable or disable the reloader. By default
the reloader is active if debug is enabled.
--debugger / --no-debugger Enable or disable the debugger. By default
the debugger is active if debug is enabled.
--eager-loading / --lazy-loader
Enable or disable eager loading. By default
eager loading is enabled if the reloader is
disabled.
--with-threads / --without-threads
Enable or disable multithreading.
--help Show this message and exit.
--host 参数特别有用,它告诉 Web 服务器在哪个网络接口上监听客户端发来的连接。默认情况下,Flask 的 Web 开发服务器监听 localhost 上的连接,因此服务器只接受运行服务器的计算机发送的连接。下述命令让 Web 服务器监听公共网络接口上的连接,因此同一网络中的其他计算机发送的连接也能接收到:
(venv) $ flask run --host 0.0.0.0
* Serving Flask app "hello"
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
现在,网络中的任何计算机都能通过 http://a.b.c.d:5000 访问 Web 服务器。其中,a.b.c.d 是运行服务器的计算机的 IP 地址。
请求–响应循环
应用和请求上下文
Flask 从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象就是一个很好的例子,它封装了客户端发送的 HTTP 请求。
为了避免大量可有可无的参数把视图函数弄得一团糟,Flask 使用上下文临时把某些对象变为全局可访问。有了上下文,便可以像下面这样编写视图函数:
from flask import request
@app.route('/')
def index():
user_agent = request.headers.get('User-Agent')
return '<p>Your browser is {}</p>'.format(user_agent)
请求分派
应用收到客户端发来的请求时,要找到处理该请求的视图函数。为了完成这个任务,Flask 会在应用的 URL 映射中查找请求的 URL。URL 映射是 URL 和视图函数之间的对应关系。Flask 使用 app.route 装饰器构建映射。
要想查看 Flask 应用中的 URL 映射是什么样子,可以在 Python shell 中审查为 app.py 生成的映射。测试之前,请确保你激活了虚拟环境:
(venv) $ python
>>> from app import app
>>> app.url_map
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/user/<name>' (HEAD, OPTIONS, GET) -> user>])
/ 和 /user/
URL 映射中的 (HEAD, OPTIONS, GET) 是请求方法,由路由进行处理。HTTP 规范中规定,每个请求都有对应的处理方法,这通常表示客户端想让服务器执行什么样的操作。Flask 为每个路由都指定了请求方法,这样即使不同的请求方法发送到相同的 URL 上时,也会使用不同的视图函数处理。HEAD 和 OPTIONS 方法由 Flask 自动处理。
响应
Flask 调用视图函数后,会将其返回值作为响应的内容。多数情况下,响应就是一个简单的字符串,作为 HTML 页面回送客户端。
但 HTTP 协议需要的不仅是作为请求响应的字符串。HTTP 响应中一个很重要的部分是状态码,Flask 默认设为 200,表明请求已被成功处理。
如果视图函数返回的响应需要使用不同的状态码,可以把数字代码作为第二个返回值,添加到响应文本之后。例如,下述视图函数返回 400 状态码,表示请求无效:
@app.route('/')
def index():
return '<h1>Bad Request</h1>', 400
如果不想返回由 1 个、2 个或 3 个值组成的元组,Flask 视图函数还可以返回一个响应对象。make_response() 函数可接受 1 个、2 个或 3 个参数(和视图函数的返回值一样),然后返回一个等效的响应对象。有时我们需要在视图函数中生成响应对象,然后在响应对象上调用各个方法,进一步设置响应。下例创建一个响应对象,然后设置 cookie:
from flask import make_response
@app.route('/')
def index():
response = make_response('<h1>This document carries a cookie!</h1>')
response.set_cookie('answer', '42')
return response
响应有个特殊的类型,称为重定向。这种响应没有页面文档,只会告诉浏览器一个新 URL,用以加载新页面。
重定向的状态码通常是 302,在 Location 首部中提供目标 URL。
from flask import redirect
@app.route('/')
def index():
return redirect('http://www.example.com')
还有一种特殊的响应由 abort() 函数生成,用于处理错误。在下面这个例子中,如果 URL 中动态参数 id 对应的用户不存在,就返回状态码 404:
from flask import abort
@app.route('/user/<id>')
def get_user(id):
user = load_user(id)
if not user:
abort(404)
return '<h1>Hello, {}</h1>'.format(user.name)
注意,abort() 不会把控制权交还给调用它的函数,而是抛出异常。