阅读 2377

一文看懂FLASK框架的基本结构

1 初始化

所有的FLASK应用都必须创建一个应用实例,Web服务器使用一种WSGI的协议把客户端(如浏览器)的所有请求都交给这个对象处理。

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

Flask类的构造函数只有一个必须指定的参数,即应用主模块或者包的名称。这个参数也不必困惑,说白了Flask用这个参数确定应用的位置,进而找到应用中其他文件的位置。

2 路由和视图函数

当你点击一个网站,客户端(如浏览器)把请求发送给Web服务器,Web服务器把请求发送给Flask应用实例。应用实例需要知道每个url的请求需要执行哪些代码,所以保存了一个URL到Python函数的映射关系。处理url和函数之间关系的程序成为路由。 Flask中定义路由最方便的方式是用装饰器app.route:

@app.route('/')
def index():
    return '<h1>hello world!</h1>'
复制代码

装饰器是Pyton语言的标准特性。常用方法是把函数注册为事件处理程序,在特定事件发生时调用。index()这样处理入站请求的函数成为视图函数,函数的返回值称为响应

Flask支持动态的url,路由url中放在尖括号里的内容就是动态部分,调用视图函数时,Flask会将动态部分作为参数传入函数。

@app.route('/user/<name>')
def user(name):
    return '<h1>hello, {}!</h1>'.format(name)
复制代码

路由中的动态部分默认使用字符串,Flask支持使用string、int、float和path类型,path类型是一种特殊的字符串,与string不同的是它可以包含正斜线。

3 一个完整的应用

## hello.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return '<h1>hello world!</h1>'
复制代码

4 Web开发服务器

Flask应用自带Web开发服务器,通过flask run启动。这个命令在FLASK_APP环境变量指定的Python脚本中寻找应用实例。若想启动上一节的hello.py
1、确保虚拟环境已经激活
2、安装了flask
3、启动web开发服务器

  • linux和macos用户
(venv)$ export FLASK_APP=hello.py
(venv)$ flask run
复制代码
  • windows用户
(venv)$ set FLASK_APP=hello.py
(venv)$ flask run
复制代码

服务器启动后开始轮询,处理请求。

  • Flask提供的开发服务器只适用于开发和测试,不能用作生产服务器。
  • Flask的web服务器也可以通过编程的方式启动:调用app.run()方法,在旧版本Flask中,启动应用在运行应用的主脚本尾部要包含:
if __name__ == '__main__':
    app.run()
复制代码

5 调试模式

Flask应用可以在调试模式中运行,在这个模式下,开发服务器默认会加载两个便利的工具:重载器调试器
启用重载器后,Flask会监视所有源代码,发现变动时自动重启服务器,在开发过程中运行启动重载器特别方便,每次改动后自动重启,大大提高生产力。
调试器是一个基于web的工具,当应用抛出未处理的异常时,信息会出现在浏览器中,web服务器变成一个交互式栈跟踪,你可以在里面审查代码,在调用栈的任何位置计算表达式。

调试模式默认是禁用的。若想启用,在执行flask run之前设置DEBUG环境变量。

(venv)$ export FLASK_APP=hello.py
(venv)$ export FLASK_DEBUG=1
(venv)$ flask run
复制代码
  • 如果想在编程启动web服务器下启动调试模式,使用app.run(debug=Ture)
  • 千万不要在生产服务器中启动调试模式,客户端通过调试器能请求执行远程代码,可能会导致生产服务器遭到攻击,作为一种简单的保护措施,启动调试器时可以要求输入PIN码。

6 命令行选项

Flask命令支持一些选项,--help可以查看哪些选项可用

(venv)$ flask --help
复制代码

--host参数特别有用,它告诉web服务器在哪个网络接口上监听客户端发来的连接,默认情况下,Flask的Web开发服务器监听localhost上的连接,因此服务器只接收web服务器所运行的计算机发送的连接。
如果想让web服务器监听公共网络上的连接

(venv)$ flask run --host 0.0.0.0
复制代码

网络上的任何计算机都能通过http://x.x.x.x:5000访问服务器,x.x.x.x是运行服务器的计算机的IP地址。

7 请求-响应循环

请求-响应循环是Flask的核心机制。

7.1 应用和请求上下文

Flask从客户端收到请求时,要让视图能访问请求对象,请求对象封装了客户端发送的HTTP请求。一中直截了当的方式是将请求对象作为参数传入视图函数,不过这会导致每个视图函数中都会多处一个参数。为了避免大量可有可无的参数把视图函数弄得一团糟,Flask使用上下文临时把某些对象变为全局可访问。

事实上,request不可能是全局变量,试想,在多线程服务器中,多个线程同时处理不同客户端发送的不同请求,每个线程看到的request对象必然不一样。Flask使用上下文让特定的变量在一个线程中全局可访问,与此同时,却不会干扰其他线程。

Flask中有两种上下文,应用上下文请求上下文,下表是两种上下文提供的变量。

变量名 上下文 说明
current_app 应用上下文 当前应用的应用实例
g 应用上下文 处理请求时用作临时存储的对象,每次请求都会重设这个变量
request 请求上下文 请求对象,封装了客户端发出的HTTP请求中的内容
session 请求上下文 用户会话,值为一个字典,存储请求之间需要“记住”的值

Flask在分派请求之前激活(或推送)应用和请求上下文,请求处理完毕后再将其删除,应用和请求上下文被push推送后,就可以使用上表中的变量了,如果使用是没有push激活,会导致错误。

7.2 请求分派

应用收到浏览器发来的请求时,要找到处理该请求的视图函数,叫做请求分派。Flask使用app.route装饰器来构建URL和视图函数的映射关系。

7.3 请求对象

Flask通过上下文变量request对外开放请求对象。这个对象包含客户端发送的HTTP请求的全部信息。请求对象中最常用的属性和方法如下。

7.4 请求钩子

在处理请求之前或者之后执行的代码会很有用,比如在请求时验证发起请求的用户身份等,为了避免每个视图中都重复写代码,Flask提供来注册通用函数的功能。请求钩子通过装饰器来实现。

7.5 响应

Flask调用视图函数之后,会将其返回值作为响应的内容。多数情况下,响应就是一个简单的字符串,作为HTTP页面回送给客户端。视图函数还可以返回状态码,默认是200,表示成功处理;400表示请求无效。

@app.route('/')
def index():
    return '<h1>bad request</h1>',400
复制代码

视图函数还可以返回一个响应对象,有时候我们需要在视图函数函数中生成响应对象,然后在响应对象上调用各个方法,进一步设置响应。响应有个特殊的类型,成为重定向。

8 Flask扩展

Flask考虑了扩展性,是一个很灵活的框架,故而没有提供一些固定的功能,例如数据库和用户身份验证,这给开发者更大的自由空间,按需选择最适合应用的包。

文章分类
后端
文章标签