一、请求钩子
在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:
-
在请求开始时,建立数据库连接;
-
在请求开始时,根据需求进行权限校验;
-
在请求结束时,指定数据的交互格式;
为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:
before_first_request:在处理第一个请求前运行。
before_request:在每次请求前运行。
after_request:如果没有未处理的异常抛出,在每次请求后运行。
teardown_request:在每次请求后运行,即使有未处理的异常抛出。需要在非调试模式(DEBUG = False)下使用。
代码:
@app.route("/index")
def index():
print("index 被执行")
a = 1 / 0
return "index page"
@app.route("/hello")
def hello():
print("hello 被执行")
return "hello page"
@app.before_first_request
def handle_before_first_request():
"""在第一次请求处理之前先被执行"""
print("handle_before_first_request 被执行")
@app.before_request
def handle_before_request():
"""在每次请求之前都被执行"""
print("handle_before_request 被执行")
@app.after_request
def handle_after_request(response):
"""在每次请求(视图函数处理)之后都被执行, 前提是视图函数没有出现异常"""
print("handle_after_request 被执行")
return response
@app.teardown_request
def handle_teardown_request(response):
"""在每次请求 (视图函数处理)之后都被执行, 无论视图函数是否出现异常,都被执行, 工作在非调试模式时 debug=False"""
path = request.path # 在一次请求中可用request.path获得请求的URL方便进行不同的处理。
if path == url_for("index"):
print("在请求钩子中判断请求的视图逻辑: index")
elif path == url_for("hello"):
print("在请求钩子中判断请求的视图逻辑: hello")
print("handle_teardown_request 被执行")
return response
钩子的请求顺序:
二、flask_script扩展
Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任务;使得脚本和系统分开;
Flask Script和Flask本身的工作方式类似,只需定义和添加从命令行中被Manager实例调用的命令;
官网分档
学得不好,看的别的博客。
2.1创建并运行命令
首先,创建一个Python模板运行命令脚本,可起名为manager.py;
在该文件中,必须有一个Manager实例,Manager类追踪所有在命令行中调用的命令和处理过程的调用运行情况;
Manager只有一个参数——Flask实例,也可以是一个函数或其他的返回Flask实例;
调用manager.run()启动Manager实例接收命令行中的命令;
#-*-coding:utf8-*-
from flask_script import Manager
from debug import app
manager = Manager(app)
if __name__ == '__main__':
manager.run()
2.2创建加入命令
- 创建Command子类
- 使用@command修饰符
- 使用@option修饰符
- 使用add_command方法
2.2.1创建Command子类
Command子类必须定义一个run方法;
#-*-coding:utf8-*-
from flask_script import Manager
from flask_script import Command
from debug import app
manager = Manager(app)
class Hello(Command):
'hello world'
def run(self):
print 'hello world'
manager.add_command('hello', Hello())
if __name__ == '__main__':
manager.run()
python manager.py hello
> hello world
2.2.2使用@command修饰符
#-*-coding:utf8-*-
from flask_script import Manager
from debug import app # 从别的py代码中导入app
manager = Manager(app)
@manager.command
def hello():
'hello world'
print 'hello world'
if __name__ == '__main__':
manager.run()
该方法创建命令的运行方式和Command类创建的运行方式相同;
python manager.py hello
> hello world
2.2.3使用@option修饰符
复杂情况下,建议使用@option;
可以有多个@option选项参数;
#-*-coding:utf8-*-
from flask_script import Manager
from debug import app
manager = Manager(app)
@manager.option('-n', '--name', dest='name', help='Your name', default='world')
#命令既可以用-n,也可以用--name,dest="name"用户输入的命令的名字作为参数传给了函数中的name
@manager.option('-u', '--url', dest='url', default='www.csdn.com')
def hello(name, url):
'hello world or hello <setting name>'
print 'hello', name
print url
if __name__ == '__main__':
manager.run()
运行方式如下:
python manager.py hello
>hello world
>www.csdn.com
python manager.py hello -n sissiy -u www.sissiy.com
> hello sissiy
>www.sissiy.com
#####2.2.4使用add_command方法
from flask_script import Server,Manger
from debug import app
manger = Manger(app)
"""
:param host: server host
:param port: server port
:param use_debugger: Flag whether to default to using the Werkzeug debugger.
This can be overriden in the command line
by passing the **-d** or **-D** flag.
Defaults to False, for security.
是否使用debug模式
:param use_reloader: Flag whether to use the auto-reloader.
Default to True when debugging.
This can be overriden in the command line by
passing the **-r**/**-R** flag.
是否自动重载。
"""
manager.add_command("runserver", Server(host='0.0.0.0', port=5000, use_debugger=True, use_reloader=True))
运行方式:
python manager.py runserver
* Serving Flask app "debug" (lazy loading)
* Environment: production
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 121-999-118
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)