接前面Python的Web框架梳理和WSGI入门笔记,了解一下Flask。
Flask是一款轻量级的用python实现的web微框架,它基于Werkzeug WSGI工具包和Jinja2模板引擎。
历史
Flask的作者是来自Pocoo的Armin Ronacher,Flask 首次发布于2010年4月1日,目前最新版本是3.0.0。
Flask 开发源于一个愚人节玩笑:Denied: the next generation python micro-web-framework 。
图片来源:http://mitsuhiko.pocoo.org/flask-pycon-2011.pdf
2016年4月Pocoo团队解散,Flask开发移交给Pallets项目。
Hello world
一个最简单的Flask程序:
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
- 首先,导入Flask类,创建其实例 app,app是一个WSGI应用程序。注意其第一个参数,用于在文件系统中查找资源文件,对单个module,
__name__
没什么问题。 - 使用装饰器
route()
,告诉Flask哪个URL会触发这个函数。
如何执行??
执行1
这是一个WSGI程序,所以,使用任何一个WSGI服务都可以启动这个程序。比如
使用 waitress
$ waitress-serve hello:app
使用 gunicorn
$ gunicorn -w 4 'hello:app'
等等...
另外,开篇我们提到了Flask依赖Werkzeug 这个 WSGI的python包,我们可以直接
import werkzeug.serving as serving
serving.run_simple('localhost', 8000, app)
也可以启用https:
import werkzeug.serving as serving
serving.run_simple('localhost', 8000, app, ssl_context=('111.cert', '111.key'))
执行2
当然,最简单的还是使用flask自带的命令行功能flask
或`python -m flask
.`:
$ flask --app hello:app run
其中
--host
参数用于修改监听地址-
--debug
参数对于调试很有用 -
--app
参数用于指定WSGI的入口
如果python脚本为 app.py 或 wsgi.py的话,且脚本内变量为app或application,可以省略--app
直接执行:
$ flask run
如果脚本是其他名字,也可以同环境变量指定
$ export FLASK_APP=hello
$ flask run
执行 3
网上好多例子都是这么写的,可能这样更简单??!
使用Flask的run()函数,直接执行这个脚本:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
当然,run也有很多参数可以配置,
run(*host=None*, *port=None*, *debug=None*, *load_dotenv=True*, ***options*)
因为它后台启动的是wekzeug的server。所以此处的options参数会传递给werkzeug.serving.run_simple()
。
在开发阶段,flask支持https也简单:
if __name__ == '__main__':
app.run('localhost', 8000, ssl_context=('111.cert', '111.key'))
路由选择 Routing
wekzeug为flask提供了routing的底层机制:
- Map
- Rule
- MapAdapter
from werkzeug.routing import Map, Rule
url_map = Map([
Rule('/all/', defaults={'page': 1}, endpoint='all_entries'),
Rule('/all/page/<int:page>', endpoint='all_entries')
])
Flask进一步进行封装
绑定
装饰器route()用于将函数绑定到一个URL地址(没有绑定的URL会报404错误):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World!'
变量规则
可以通过<variable_name>
将变量添加进URL,而后在函数中可以直接使用该变量。也可以为变量指定转换器,格式<converter:variable_name>
:
@app.route('/user/<username>')
def show_user_profile(username):
return f'User {username}'
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'Post {post_id}'
转换器类型:
- string:默认。接受斜杠外其他文字
- int:正整数
- float:正浮点数
- path:类似string,但接受斜杠
- any:
- uuid:接收UUID字符串
唯一URL与重定向行为
路径是否以/
结尾,有不同效果:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
-
前者接受
/projects
和/projects/
-
后者只接受
/about
,而/about/
会触发404错误。对应唯一的URL
HTTP方法
route中可以指定methods。如果处理不同method时,用相同的数据,可以放到一个函数中:
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()
- 注意:methods 默认是
GET
(隐含能处理HEAD
)。 - route的其他参数:
endpoint
(默认用view function的名字)、view_func
、defaults
、subdomain
等
如果要拆开的话,也可以用更简单的形式:
@app.get('/login')
def login_get():
return show_the_login_form()
@app.post('/login')
def login_post():
return do_the_login()
参考
- https://github.com/pallets/flask
- https://flask.palletsprojects.com
- https://en.wikipedia.org/wiki/Flask_(web_framework)
- http://mitsuhiko.pocoo.org/flask-pycon-2011.pdf
- https://palletsprojects.com/p/jinja/
- https://werkzeug.palletsprojects.com