Flask 学习笔记:Flask应用的基本架构

1 知识储备

在学习Flask应用之前,让我们先了解一些术语。

1.1 Web服务器

  • Web服务器是一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载
  • 目前主流的Web服务器有:TomcatNginxIIS

1.2 Web应用程序

1.3 认识WSGI-Web服务器网关接口

  • WSGI,是Python语言定位的Web服务器与Web应用程序或框架之间的一种简单而通用的接口
  • WSGI没有官方实现,更像是一种协议,主要遵循这种协议,WSGI应用程序都可以在任何服务器上部署、运行,反之亦然
  • WSGI分为两个部分,一个是“服务器”或者“网关”,一个是“应用程序”或者“应用框架”。在处理WSGI请求时,服务器会为应用程序提供环境信息以及一个回调函数;当应用程序完成处理请求后,通过回调函数将结果信息返回给服务器

2 Flask应用基本结构

2.1 Flask初始化

实例化Flask对象是编写Flask应用程序的第一步。实例化的Flask即可实例化一个WSGI应用程序,并充当核心对象。该过程需要传入应用程序的模块或包的名称。一旦该对象成功,它将成为View FunctionURL RulesTemplate Configuration等的核心注册对象。

Flask初始化很简单,只需传入一个参数,即应用程序主模块或包的名称,一般传入__name__即可,示例代码如:

from flask import Flask
app = Flask(__name__)

2.1.1 理解Flask传入的第一个参数

Flask应用程序可根据这个参数,从当前包或者包含当前模块(.py文件)的文件夹内查询资源;另外,Flask的扩展也可根据这个参数优化调试信息等等。

官网建议,如果使用一个单独的模块(即:一个独立的.py文件),传入__name__即可;如果使用一个包(含__init__.py文件的文件夹),通常建议此处填入包的名称;如果这种情况仍然传入__name__,程序也可以正常运行,不过在测试环境中,某个扩展可能会出现意想不到的问题。

2.2 路由

2.2.1 什么是路由

客户端将请求发送给Web服务器,然后Web服务器将请求转发给Flask应用示例。而,应用示例接收到URL请求后需要知道它该运行哪些代码,所需要保存URL和函数的映射对应关系,而存储这些关系的就是路由

2.2.2 定义路由

Flask中定义路由有两种方式:

  • 简便的方式,使用应用实例提供的app.route装饰器,如下:
@app.rout("\")
def index():
    return '<h1>Hello World</h1>'
  • 传统的方式,使用app.add_url_rule方法,该方法接收3个参数:URL、断点(endpoint)和视图函数,如下:
def index():
    return '<h1>Hello World</h1>'

app.add_url_rule('/', 'index', index)

处理类似index这种入站请求的函数统称为视图函数

2.2.3 定义动态路由

Flask支持动态路由,只需在URL中使用对应的句法即可,例如/user/<name>,其中<>中的内容就是动态的,其他内容是该URL中静态部分,Flask会将动态部分作为参数传入给视图函数。

Flask中动态部分默认是字符串类型,也可以显示定义其他类型,例如:intfloatpath,其中,path类型是一种特殊的字符串,它可以包含正斜线。

2.3 Web开发服务器

Flask中自带Web开发服务器,可通过flask run命令启动,需提前配置FLASK_APP环境变量,给该命令指定从哪个Python脚本中寻找应用示例。

以运行hello.py这个文件为例

# Linux和MacOS
export FLASK_APP=hello.py
flask run

# Windows
set FLASK_APP=hello.py
flask run

Web开发服务器启动后,便开始轮训,处理请求,直到该服务器停止。

除了使用flask run的方式,也可以使用编程的方式启动:调用app.run方法。在之前旧版本中,若想启动应用,需要运行应用的主脚本,该主脚本需要在其尾部增加如下内容:

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

现有版本中,常使用flask run命令启动,不过在单元测试中,也可使用编程方式启动应用。

2.4 调试模式

Flask调试模式默认会加载两个便利的工具:重载器和调试器。

  • 重载器

启用重载器后,Flask会监听项目中所有的源代码文件,发现变动后自动重启服务器。

  • 调试器

调试器是基于Web工具,当应用跑出未处理的异常时,它会出现在浏览器中。

启用调试模式方式如下:

  • 当使用flask run命令

在使用flask run之前设定FLASK_DEBUG=1环境变量

  • 当使用app.run()方式

当使用这种方式时,需传递参数debug=True,即app.run(debug=True)

2.5 请求-响应循环

2.5.1 应用和请求上下文

Flask从客户端接收到请求后,会使用临时上下文将某些对象变为全局访问,以便让视图函数能够访问,从而处理这些请求,其调用方式如下:

from flask import request

需要提醒的是,request只是被当做全局变量访问,但事实上肯定不会是全局变量。因为,在多线程Web服务器中,多个线程同时处理不同客户端发送的请求时,每个线程接收到的request对象必然是不同的。

Flask中,上下文可分为应用上下文请求上下文,如下:

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

Flask在分派请求之前激活(或者推送)应用和请求上下文,请求处理完成之后再将其删除。也就是,应用上下文被推送之后,就可以在当前线程中使用current_appg变量;请求上下文被推送之后,就可以在当前线程中使用requestsession变量。如果在没有激活应用上下文或者请求上下文之前使用这些变量,将会导致错误。

  • request对象常用属性和方法
属性或方法 说明
form 一个字典,存储请求提交的所有表单字段
args 一个字典,存储通过URL查询字符串传递的所有参数
values 一个字典,formargs的合集
cookies 一个字典,存储请求的所有的cookie
headers 一个字典,存储请求所有的HTTP首部
files 一个字典,存储请求上传的所有文件
get_data() 返回请求主体缓冲的数据
get_json() 返回一个字典,包含解析请求主体后得到的JSON
blueprint 处理请求的Flask蓝本的名称
endpoint 处理请求的Flask端点的名称,Flask会将视图函数的名称用作路由端点的名称
method HTTP请求方法,例如GETPOST
scheme URL方案,httphttps
is_secure() 通过安全的链接(HTTPS)发送请求时返回True
host 请求定义的主机名,如果客户端定义了端口号,还包括端口号
path URL路径部分
query_string URL的查询字符串部分,返回原始的二进制值
full_path URL路径和查询字符串部分
url 客户端请求的完整的URL
base_url url,但没有查询字符串部分
remote_addr 客户端的IP地址
environ 请求的原始WSGI环境字典

2.5.2 请求分派

Flask为了完成将客户端发来的请求与视图函数相对应,会从应用的URL映射中查找请求的URL。URL映射是URL和视图函数之间的对应关系。

若想查看Flask中定义的URL映射会是什么样子,可调用应用实例的url_map属性,如下:

from hello.py import app
app.url_map

2.5.3 请求钩子

有时我们需要在请求之前和请求之后执行相关代码,例如,在请求开始时,可能需要创建数据库连接或者验证发起请求的用户身份。

Flask提供注册通用函数的功能,注册的函数可在请求被分派到视图函数之前或之后调用,通用注册函数有:

  • before_request

注册一个函数,在每次请求之前运行

  • before_first_request

注册一个函数,只在处理第一个请求之前运行。可以通过这个钩子添加服务器初始化任务

  • after_request

注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行

  • teardown_request

注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行

在请求钩子函数和视图函数之间共享数据一般会用应用上下文全局变量g

2.5.4 响应

Flask调用视图函数后,会将其返回值作为响应内容。一般情况下,响应及时一个简单的字符串,作为HTML页面返回给浏览器端。

Flask响应可包括3个参数,第一个参数是上面提到的响应内容,第二个参数是状态码,默认为200,第三个参数是HTTP响应头部组成的字符串。

Flask视图函数还可以返回一个响应对象make_response(),该函数可接受1、2或3个参数(与视图函数的返回值相对应),即make_response会返回一个等效的响应对象。

响应对象常用属性和方法如下:

属性或方法 描述
status_code HTTP数字状态码
headers 一个类似字典的对象,包含随响应发送的所有首部
set_cookie() 为响应添加一个cookie
delete_cookie() 删除一个cookie
content_length 响应主体的长度
content_type 响应主题的媒体类型
set_data() 使用字符串或字节值设定响应
get_data() 获取响应主体

一些特殊的响应

  • 重定向响应

重定向响应没有页面文档,只会告诉浏览器一个URL,用来加载新页面。该响应对应的状态为302,在Location首部提供目标URL

Flask中提供了redirect()辅助函数,用来生成这种响应,如下:

from flask import redirect

@app.rout("/")
def index():
    return redirect("http://www.baidu.com")
  • 错误响应

Flask中可用abort函数生成该响应,如下:

from flask import abort

@app.rout("/usr/<id>")
def get_user(id):
    user = load_user(id)
    
    if not user:
        abort(404)
    return '<h1>hello</h1>'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章