安装
Flask主要有两个依赖:Werkzeug(负责路由、调试、WSGI)和Jinja2(负责模板)
先搭虚拟环境
虚拟环境是python解释器的一个私有副本(就像开小号),在这个环境中你可以随意造次,并且不会影响系统中的全局Python解释器,我是Win环境,需要有pip,然后在Powershell(cmd也可)里敲命令安装
Linux下:
$ sudo agt-get install python-virtualenv
Win下(注意用管理员身份):
pip install virtualenv
安装完毕后检查一下,显示版本号说明安装成功:
virtualenv --version
下一步进入一个文件夹(最好是新建),在里面创建虚拟环境(参数是虚拟环境的名字,我的是Myenv
):
PS S:\envA> virtualenv Myenv
Using base prefix 'c:\\program files (x86)\\python36-32'
New python executable in S:\envA\Myenv\Scripts\python.exe
Installing setuptools, pip, wheel...done.
成功后文件夹里多了一个Myenv文件夹,里面保存着虚拟环境,使用的时候需要激活,命令如下:
Linux下:
$ source Myenv/bin/activate
Win下(注意目录位置):
$ .\Myenv\Scripts\activete
这里我用Powshell出现了一个错误:
.\activate : 无法加载文件 S:\envA\Myenv\Scripts\activate.ps1,因为在此系统上禁止运行脚本。有关详细 信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
查完发现是执行策略的问题,Powershell第一次运行时用的是Restricted(默认设置),该策略不允许任何脚本运行,用 get-executionpolicy
一看果然是,那就改成RemoteSigned,用 set-executionpolicy remotesigned
命令后就可以了,成功进入后命令行提示符的前面会加上环境名字:(Myenv) PS S:\envA>
Powershell脚本的4种执行权限:
- Restricted——默认的设置, 不允许任何script运行
- AllSigned——只能运行经过数字证书签名的script
- RemoteSigned——运行本地的script不需要数字签名,但是运行从网络上下载的script就必须要有数字签名
- Unrestricted——允许所有的script运行
如果用完了虚拟环境想退出来,就用deactivate
命令
安装Flask
就一行:pip install flask
, 在虚拟环境里输入即可(如果没进venv就安装在了全局里)
第一个程序
从程序实例开始
所有Flask程序必须创建一个程序实例(即Flask类的对象),服务器使用WSGI(简单说就是python程序与web服务器之间的一个接口)的协议,把接收到的请求都交给这个对象处理,创建如下:
from flask import Flask
app = Flask(__name__) # 只有一个参数__name__,用该参数决定程序的根目录,便于以后找资源
路由
为了知道程序实例对每个URL请求运行哪些代码,所以保存一个URL到python函数的映射关系,处理URL和函数之间的关系的程序称为路由
程序实例提供了app.route()
装饰器,可以轻松将视图函数(即函数)装饰为路由,而且还可以动态传入参数,就像这样:
@app.route('/') # 这里将视图函数index注册为程序根地址
def index():
return '<h1>Hi~ Im Index</h1>'
@app.route('/user/<name>') # 尖括号内的动态部分作为参数传入user中
def user(name):
return '<h1>hello, %s!</h1>' % name
视图函数的返回值称为响应,是客户端接收到的内容,可以是HTML的简单字符串,也可以是复杂表单
动态部分默认使用字符串,也可以用类型定义,如:'路由/user/<int:id>'
只匹配id为整数的URL
路由动态部分的类型定义:字符串,int,float,path(也是字符串但不把斜线视作分隔符)
运行服务器
程序实例用run
方法启动,有一些启动参数如调试器(较常用,debug=True
)和重载程序,随后服务器会进入轮询,等待并处理请求,Ctrl-C
可以直接停止
完整代码
# demo.py 文件名
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hi~ Im Index</h1>'
@app.route('/user/<name>')
def user(name):
return '<h1>hello, %s!</h1>' % name
if __name__ == '__main__':
app.run(debug=True)
运行如下:
(Myenv) PS S:\envA> python .\demo.py
* Restarting with stat
* Debugger is active!
* Debugger PIN: 317-394-910
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
访问首页和欢迎页:
框架的一些设计理念
上下文
视图函数可以根据请求去访问一些对象,请求对象封装了客户端发送的HTTP请求
直白的方法是把请求对象作为参数传入视图函数进行访问,不过这样会使每个视图函数都添加一个参数,而且当需要同时访问其他对象时会更麻烦,难以维护,好在Flask用了上下文把一些对象变为全局可访问(在一个线程中),见下例:
from flask import request
@app.route('/')
def index():
user_agent = request.headers.get('User-Agent') # 获取请求上下文中的UA
return '<p>browser: %s</p>' % user_agent
Flask的两种上下文
- 程序上下文:
current_app
(当前的程序实例),g
(处理请求时用作临时存储的对象,每次请求会重设)- 请求上下文:
request
(请求对象,封装了HTTP请求内容),session
(用户会话,存储请求之间需要”记住”的值的字典)
上下文需要激活(或推送)后才能调用,请求处理完成后再将其删除,若没推送就使用上下文会导致错误:RuntimeError:working outside of application context
, 调用app.app_context()
可获得一个程序上下文
URL映射
URL映射是URL和视图函数之间的对应关系,当根据请求找视图函数时会在URL映射中寻找请求的URL
用app.route
装饰器和app.add_url_rule()
都可以生成映射,检查映射用app.url_map
:
>>> app.url_map
Map([<Rule '/' (GET, OPTIONS, HEAD) -> index>, # 首页君
<Rule '/static/<filename>' (GET, OPTIONS, HEAD) -> static>, # 用于访问静态文件的路由
<Rule '/user/<name>' (GET, OPTIONS, HEAD) -> user>]) # 之前注册的动态路由
其中OPTIONS、HEAD、GET都是请求方法,不同请求方法使用不同视图函数处理,前两个由Flask自动处理,所以在这个程序里相当于都用了GET方法
请求钩子
有时会有在处理请求之前或之后执行代码的情况,比如在请求最开始的数据库连接、认证等,Flask提供注册通用函数的功能(即请求钩子),当然也是用装饰器实现的
4种请求钩子:
- before_first_request: 注册一个函数,在处理第一个请求之前运行
- before_request:~,在每次请求之前运行
- after_request:~,如果没有未处理的异常抛出,在每次请求之后运行
- teardown_request:~,即使有未处理的异常抛出,也在每次请求之后运行
在请求钩子函数和视图函数之间用程序上下文变量g来实现数据的共享
响应
为了服从HTTP协议,视图函数的返回值里需要有状态码,即把数字代码作为第二个返回值,跟在相应文本之后,Flask默认为200;除了状态码还可以接收第三个参数:由header
组成的字典
视图函数除了返回由1-3个值组成的元祖,还可以返回Response
对象,make_response()
函数可接收1-3个参数,并返回一个Response
对象,下例返回了response对象:
from flask import make_response
@app.route('/')
def index():
response = make_response('<h1>set cookie idnex</h1>')
response.set_cookie('answer', '666')
return response
特殊响应
重定向(302):指向一个新地址(由Location
首部提供),除了用返回值和response
对象,用redirect()
更为方便
abort生成(404):用于处理错误,抛出异常并把控制权交给web服务器
Flask-Script扩展
虽然Flask的web服务器支持很多启动设置选项,但只能在脚本中作为参数传给程序实例的run()
方法,极为不便,所以选用这个拓展,它为Flask程序添加一个命令行解析器,不仅自带常用选项,而且还支持自定义命令,安装只需一行码:
pip install flask-script
初始化,把程序实例作为参数传给构造函数,初始化主类的实例后就可以使用:
from flask_script import Manager
...
manager = Manager(app)
...
if __name__ == '__main__':
manager.run()
运行后可以看到参数,shell
是在程序的上下文中启动python会话,runserver
即启动web服务器,根据需要自行选择:
usage: demo.py [-?] {shell,runserver} ... positional arguments: {shell,runserver} shell Runs a Python shell inside Flask application context. runserver Runs the Flask development server i.e. app.run() optional arguments: -?, --help show this help message and exit
runserver
也有很多选项,具体在后面加个--help
就能看到,要说一下--host
参数,它管理web服务器监听来自客户端的连接,默认情况是监听localhost上的连接,如果要允许同网中的其他计算机连接服务器需要设为--host 0.0.0.0
,这样一来就可以用外网IP来访问