在下面这些情况下,Flask会自动帮我们激活程序上下文。

1.当我们使用flask run命令启动程序时。

2.使用旧的app.run()方法启动程序时。

3.执行使用@app.cli.command()装饰器注册的flask命令时。

4.使用flask shell命令启动Python shell时。

当请求进入时,Flask会自动激活请求上下文,这时我们可以使用request和session变量。另外,当请求上下文被激活时,程序上下文被自动激活。当请求处理完毕后,请求上下文和程序上下文会自动销毁。也就是说,在请求处理时这两者拥有相同的声明周期。

结合Python的代码执行机制理解,这也就意味着,我们可以在视图函数中或者视图函数内部调用的函数/方法中使用所有上下文全局变量。在使用flask shell命令打开的Python Shell中,或是自定义的flask命令函数中,我们可以使用current_app和g变量,也可以手动激活请求上下文来使用request和session。

如果我们在没有激活相关上下文时使用这些变量,Flask就会抛出RuntimeError异常:“RuntimeError:Working outside of application context.”或是“RuntimeError:Working outside of request context.”。

同样依赖于上下文的还有url_for()、jsonify()等函数,所以也只能在视图函数中使用它们。其中jsonify()函数内部调用中使用了current_app变量,而url_for()则需要依赖请求上下文才可以正常运行。

如果需要在没有激活上下文的情况下使用这些变量,可以手动激活上下文。程序上下文使用app.app_context()获取,我们可以使用with语句执行上下文操作:

from app import app
from flask import current_app
with app.app_context():
    current_app.name
'app'

或是显式地使用push()方法推送(激活)上下文,在执行完相关操作时使用pop()方法销毁上下文:

>>> from app import app
>>> from flask import current_app
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>> current_app.name
'app'
>>> app_ctx.pop()

而请求上下文可以通过test_request_context()方法临时创建

>>> from app import app
>>> from flask import request
>>> with app.test_request_context('/hello'):
        request.method
'GET'

同样的,这里也可以使用push()和pop()方法显式地推送和销毁请求上下文。

上下文钩子

Flask也为上下文提供了一个teardown_appcontext钩子,使用它注册的回调函数会在程序上下文被销毁时调用,而且通常也会在请求上下文被销毁时调用。比如,你需要在每个请求处理结束后销毁数据库连接:

@app.teardown_appcontext
def teardown_db(exception):
    db.close()

0 Comments latest

No comments.