Auth: 王海飞
Data:2018-09-15
Email:[email protected]
在Web开发中经常会对所有的请求做一些相同的操作,如果将相同的代码写入每一个视图函数中,那么程序就会变得非常臃肿。为了避免在每个视图函数中定义相同的代码,可以使用钩子函数。如下有三个常见的钩子:
-
before_request: 被装饰的函数会在每个请求被处理之前调用。
-
after_request: 被装饰的函数会在每个请求退出时才被调用。在程序没有抛出异常的情况下,才会被执行。
-
teardown_request: 被装饰的函数会在每个请求退出时才被调用。不论程序是否抛出异常,都会执行。
注意:
1. 这个异常是指代码本身错误(代码中出现10/0)不执行,如果abort抛出异常了,after_request还是会执行。
2. 必须配置app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False。该配置表示无论如何都将执行teardown_request装饰的方法。
@blue.before_request
def before_request():
print('before_request')
@blue.after_request
def after_request(response):
print('after_request')
return response
@blue.teardown_request
def teardown_request(exception):
print('teardown_request')
@blue.route('index/')
def index_requst():
return 'index_requst'
分析:访问http://127.0.0.1:8080/app/index/后,在控制台可以看到如下输出:
before_request
after_request
teardown_request
从控制台的输出中可以看出各函数的执行顺序,被before_request装饰的函数会在请求处理之前被调用。而after_request和teardown_request会在请求处理完后才被调用。区别就在于after_request只会在请求正常退出的情况下才会被调用,并且atfer_request函数必须接受一个响应对象,并返回一个响应对象。而teardown_request函数在任何情况下都会被调用,并且必须传入一个参数来接收异常对象。
应用全局对象(g)是Flask为每一个请求自动建立的一个对象。g的作用范围只是在一个请求(也就是一个线程)里,它不能在多个请求中共享数据,故此应用全局变量(g)确保了线程安全。
@blue.before_request
def get_mysql_connect():
# 建立mysql数据库的连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', database='f_db')
cursor = conn.cursor()
# 设置当前请求上下文中的应用全局对象
g.conn = conn
g.cursor = cursor
@blue.before_request
def create_student_table():
# 创建student表
sql = 'drop table if exists student;'
sql1 = 'create table student(id int auto_increment, s_name varchar(10) not null, s_age int not null, primary key(id)) engine=InnoDB default charset=utf8;'
# 执行删除表,如果student表存在则删除
g.cursor.execute(sql)
# 执行创建student表
g.cursor.execute(sql1)
@blue.route('excute_sql/')
def excute_sql():
# 定义插入sql语句
sql = 'insert into student (name, age) values ("%s", "%s")' % ('xiaoming', '18')
# 执行插入语句
g.cursor.execute(sql)
# 提交事务
g.conn.commit()
return '创建数据'
@blue.teardown_request
def close_mysql_connect(exception):
# 关闭mysql数据库的连接
g.conn.close()