一、虚拟环境配置
1.1 创建虚拟环境
Python 3 和 Python 2 解释器创建虚拟环境的方法有所不同。在 Python 3中,虚拟环境由 Python 标准库中的 venv 包原生支持。
使用如下命令创建虚拟环境:
python -m venv virtual-environment-name
-m venv
选项的作用是以独立的脚本运行标准库中的 venv 包,后面的参数为虚拟环境的名称。
例如,如下命令创建了一个名称为venv的虚拟环境:
python -m venv venv
命令执行完毕后,当前目录中会出现一个名为 venv 的子目录,这里就是一个全新的虚拟环境,包含这个项目专用的 Python 解释器。
1.2 激活虚拟环境
在Windows下,可以通过如下命令激活虚拟环境:
venv/Scripts/aivate
虚拟环境激活后,命令行的路径前会有(venv)
,此时在命令行中输入python,将调用虚拟环境中的解释器,而不是全局解释器。如果打开了多个命令提示符窗口,则在每个窗口中都要激活虚拟环境。
在命令提示符中输入deactivate,则可以退出当前虚拟环境,还原为PATH环境变量。
1.3 在虚拟环境中安装包
在激活虚拟环境后,同样可以使用pip包管理器来进行python包的安装。
pip install flask
可以使用pip freeze
命令查看虚拟环境中安装了哪些包
1.4 踩坑
(1)我实在windows下进行的配置,因为电脑上同时安装了python2和python3,所以之前把python3的解释器名字改为了python3.exe
,但是使用python3
命令创建venv虚拟环境会报错,将python3.exe
改回python.exe
,再用python
命令即可成功创建。
(2)在创建并激活虚拟环境后,发现解释器和pip管理器依然是全局的,后来将路径中的中文去掉,使用全英文路径即可。
二、应用的基本结构
2.1 初始化
所有Flask应用都必须创建一个应用实例,应用实例是Flask类的对象,通常由下述代码创建:
from flask import Flask
app = Flask(__name__)
Flask 类的构造函数只有一个必须指定的参数,即应用主模块或包的名称。在大多数应用中,Python 的 __name__
变量就是所需的值。
2.2 路由和视图函数
处理 URL 和函数之间关系的程序称为路由 。在 Flask 应用中定义路由的最简便方式,是使用应用实例提供的app.route
装饰器。、
下面的例子说明了如何使用这个装饰器声明路由,其将index()函数注册为根地址的处理程序:
@app.route('/')
def index():
return '<h1>Hello World!</h1>'
除此之外,还能使用动态的路由:
@app.route('/user/<name>')
def user(name):
return '<h1>Hello, {}!</h1>'.format(name)
路由的<name>
中的内容就是动态部分,任何能匹配静态部分的 URL 都会映射到这个路由上。调用视图函数时,Flask 会将动态部分作为参数传入函数。
路由中的动态部分默认使用字符串,不过也可以是其他类型。
例如,路由 /user/<int:id>
只会匹配动态片段 id 为整数的 URL,例如/user/123
。
Flask 支持在路由中使用 string 、int 、float 和 path 类型。path 类型是一种特殊的字符串,与 string 类型不同的是,它可以包含正斜线。
2.3 一个完整的应用
使用一个应用实例、一个路由和一个视图函数可以组成一个完整的Flask应用hello.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hello World!</h1>'
2.4 Web开发服务器
若想启动上面编写的hello.py应用,首先激活虚拟环境。
(1)Linux和macOS用户使用如下命令:
export FLASK_APP=hello.py
flask run
(2)在Windows下
如果你的 Terminal 用的是 cmd,则使用如下命令:
set FLASK_APP=hello.py
flask run
如果你的 Terminal 用的是 powershell,则使用如下命令:
$env:FLASK_APP=".\hello.py"
flask run
默认的端口是5000,此时再访问http:localhost:5000/
即可
2.5 动态路由
在hello.py的基础上增加一个动态路由:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hello World!</h1>'
@app.route('/user/<name>')
def users(name):
return '<h1>Hello {}</h1>'.format(name)
此时访问http://localhost:5000/user/Lethe,则会显示Hello Lethe
2.6 调试模式
调试模式默认禁用,若想启用,在执行 flask run 命令之前设定环境遍历 FLASK_DEBUG=1即可。
千万不要在生产服务器中启用调试模式。
2.7 命令行选项
(1)flask shell
命令在应用的上下文中打开一个 Python shell 会话。在这个会话中可以运行维护任务或测试,也可以调试问题。
(2)flask run 命令我们已经用过,它的作用是在 Web开发服务器中运行应用,可以使用 flask run --help查看该命令的具体参数使用。
其中 --host
参数可以告诉Web服务器在哪个网络接口上监听客户端发来的连接。默认情况下,Flask 的 Web 开发服务器监听 localhost 上的连接。要写监听公网上的连接,则需要如下启动命令:
flask run --host 0.0.0.0
2.8 请求-响应循环
2.8.1 应用和请求上下文
在 Flask 中有两种上下文:应用上下文 和请求上下文。
应用上下文包括:
- current_app:当前应用的应用实例
- g:处理请求时用作临时存储的对象,每次请求都会重设这个
变量
请求上下文包括:
- request:请求对象,封装了客户端发出的 HTTP 请求中的内容
- session:用户会话,值为一个字典,存储请求之间需要“记住”的值
Flask 在分派请求之前激活(或推送 )应用和请求上下文,请求处理完成后再将其删除。应用上下文被推送后,就可以在当前线程中使用current_app 和 g 变量。类似地,请求上下文被推送后,就可以使用request 和 session 变量。如果使用这些变量时没有激活应用上下文或请求上下文,就会导致错误。
由于这一部分对于初学者来说比较难理解,推荐阅读此文章:http://www.bjhee.com/flask-ad1.html
2.8.2 请求对象
Flask 通过上下文变量 request 对外开放请求对象,此对象包含客户端发送的HTTP请求的全部信息。
Flask请求对象常用属性和方法如下:
- form:一个字典,存储请求提交的所有表单字段
- args:一个字典,存储通过 URL 查询字符串传递的所有参数
- values:一个字典, form 和 args 的合集
- cookies: 一个字典,存储请求的所有 cookie
- headers :一个字典,存储请求的所有 HTTP 首部
- files: 一个字典,存储请求上传的所有文件
- get_data(): 返回请求主体缓冲的数据
- get_json(): 返回一个 Python 字典,包含解析请求主体后得到的 JSON
- blueprint:处理请求的 Flask 蓝本的名称;蓝本在第 7 章介绍
- endpoint:处理请求的 Flask 端点的名称;Flask 把视图函数的名称用作路由端点的名称
- method: HTTP 请求方法,例如 GET 或 POST
- scheme: URL 方案( http 或 https )
- is_secure(): 通过安全的连接(HTTPS)发送请求时返回 True
- host: 请求定义的主机名,如果客户端定义了端口号,还包括端口号
- path: URL 的路径部分
- query_string: URL 的查询字符串部分,返回原始二进制值
- full_path: URL 的路径和查询字符串部分
- url: 客户端请求的完整 URL
- base_url: 同 url ,但没有查询字符串部分
- remote_addr: 客户端的 IP 地址
- environ: 请求的原始 WSGI 环境字典
2.8.3 请求钩子
请求钩子通过装饰器实现,可以将某个函数装饰为一个请求钩子,在请求开始或结束时自动调用被修饰的函数内容。
Flask 支持以下 4 种钩子:
- before_request:注册一个函数,在每次请求之前运行。
- before_first_request:注册一个函数,只在处理第一个请求之前运行。可以通过这个钩子添加服务器初始化任务。
- after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。
- teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。
2.8.4 响应
(1)Flask 调用视图函数后,会将其返回值作为响应的内容。
可以通过设置返回值的第二个参数来返回不同的状态码,如返回400:
@app.route('/')
def index():
return '<h1>Bad Request</h1>', 400
视图函数返回的响应还可接受第三个参数,这是一个由 HTTP 响应首部组成的字典。
(2)除此之外,还可以返回一个响应对象。make_response() 函数接收与返回值一样的参数,然后返回一个响应对象。
这么做的目的是可以通过此返回对象调用各个方法,进一步设置相应。
如下创建一个相应对象,然后设置cookie:
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/')
def index():
response = make_response('<h1>This document carries a cookie!<h1/>')
response.set_cookie('answer', '42')
return response
这样在访问时,返回的同时也会设置一个cookie。
Flask响应对象常用的属性和方法如下:
- status_code: HTTP 数字状态码
- headers:一个类似字典的对象,包含随响应发送的所有首部
- set_cookie(): 为响应添加一个 cookie
- delete_cookie(): 删除一个 cookie
- content_length: 响应主体的长度
- content_type: 响应主体的媒体类型
- set_data(): 使用字符串或字节值设定响应
- get_data(): 获取响应主体
(3)重定向
如果要使用重定向(302),在Flask中提供了 redirect()函数,用于生成重定向响应:
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/')
def index():
return redirect('http://www.baidu.com')
(4)处理错误
还有一种特殊的响应由 abort() 函数生成,用于处理错误,其不会把控制权交还给调用它的函数,而是抛出异常。
from flask import Flask, abort
app = Flask(__name__)
@app.route('/answer/<int:id>')
def get_user(id):
if id != 1:
abort(404)
return '<h1>answer=1</h1>'
上例访问 /user/1
时会返回answer=1
,若<id>
不1,则返回404。