Flask:基本结构
在大多数标准中,Flask 都算是小型框架,小到可以称为“微框架”。但是,小并不意味着它比其他框架的功能少。Flask 自开发伊始就被设计为可扩展的框架,它具有一个包含基本服务的强健核心,其他功能则可通过扩展实现。Flask有3个主要依赖:路由、调试和 Web 服务器,网关接口(WSGI,Web server gateway interface)子系统由 Werkzeug 提供;模板系统由 Jinja2 提供;命令行集成由 Click 提供。
1、最小程序
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hello World!</h1>'
2、动态路由
动态部分默认为字符串类型,可以指定类型和别名,支持的类型包括 string
、int
、float
和 path
。
@app.route('/user/<name>')
def user(name):
return '<h1>Hello, {}!</h1>'.format(name)
@app.route('/user/<int:id>')
def get_user(id):
return f'type(id):{type(id)}'
3、内建服务器
Bash Shell:
(venv) $ export FLASK_APP=hello.py
(venv) $ export FLASK_DEBUGE=1
(venv) $ flask run
(venv) $ flask run --host 0.0.0.0
(venv) $ flask run --help
(venv) $ flask shell
CMD:
(venv) > set FLASK_APP=hello.py
(venv) > set FLASK_DEBUG=1
(venv) > flask run
4、请求
4.1 应用上下文和请求上下文
为了让视图函数能够访问请求对象,可以直接将请求对象传入视图函数,为了避免大量可有可无的参数把视图函数弄得一团糟,Flask 使用上下文临时把某些对象变为全局可访问。
在多线程服务器中,多个线程同时处理不同客户端发送的不同请求时,每个线程看到的 request
对象必然不同。Flask 使用上下文让特定的变量在一个线程中全局可访问,与此同时却不会干扰其他线程。
变量名 | 上下文 | 说明 |
---|---|---|
current_app |
应用上下文 | 当前应用的应用实例 |
g |
应用上下文 | 处理请求时用作临时存储的对象,每次请求都会重设这个变量 |
request |
请求上下文 | 请求对象,封装了客户端发出的 HTTP 请求中的内容 |
session |
请求上下文 | 用户会话,值为一个字典,存储请求之间需要“记住”的值 |
-
应用上下文被推送后,就可以在当前线程中使用
current_app
和g
变量。 -
请求上下文被推送后,就可以使用
request
和session
变量。
4.2 请求分派
请求到来时,Flask会在URL映射中查找对应的视图函数,通常使用app.route()装饰器构建映射。app.url_map
参数可以查看url映射表。
4.3 请求钩子
有时在处理请求之前或之后执行代码会很有用。例如,在请求开始时,可能需要创建数据库连接或者验证发起请求的用户身份。为了避免在每个视图函数中都重复编写代码,Flask 提供了注册通用函数的功能,注册的函数可在请求被分派到视图函数之前或之后调用。
钩子函数 | 说明 |
---|---|
before_request |
注册一个函数,在每次请求之前运行 |
before_request |
只在处理第一个请求之前运行 |
after_request |
如果没有未处理的异常抛出,在每次请求之后运行 |
teardown_request |
即使有未处理的异常抛出,也在每次请求之后运行 |
4.4 请求方法
Web 应用使用不同的 HTTP 方法处理 URL 。当你使用 Flask 时,应当熟悉 HTTP 方法。 缺省情况下,一个路由只回应 GET
请求。 可以使用 route()装饰器的 methods
参数来处理不同的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
如果当前使用了 GET 方法, Flask 会自动添加 HEAD
方法支持,并且同时还会 按照 HTTP RFC 来处理 HEAD
请求。同样, OPTIONS
也会自动实现。
5、响应
返回一个元组:
return 'Hello'
return 'Hello', 200
return '<h1>Bad Request</h1>', 400, dict(xxx=...)
返回响应对象:
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return res
返回重定向:
return redirect('http://www.example.com')
return redirect(url_for('index'))
返回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)
6、构建URL
函数 | 结果 |
---|---|
url_for('index') |
/ |
url_for('index', _external=True) |
http://localhost:5000/ |
url_for('user', name='john', _external=True) |
http://localhost:5000/user/john |
url_for('user', name='john', page=2, version=1) |
/user/john?page=2&version=1 |
生成连接应用内不同路由的链接时,使用相对地址就足够了。如果要生成在浏览器之外使用的链接,则必须使用绝对地址,例如在电子邮件中发送的链接。
7、使用静态文件
静态文件默认放在应用的 /static 目录中。
生成相应的 URL:url_for('static', filename='css/styles.css')