1、关于上下文的介绍
Flask项目中有两个上下文,一个是应用上下文(app),另外一个是请求上下文(request)。请求上下文request和应用上下文current_app都是一个全局变量。所有请求都共享的。Flask有特殊的机制可以保证每次请求的数据都是隔离的,即A请求所产生的数据不会影响到B请求。所以可以直接导入request对象,也不会被一些脏数据影响了,并且不需要在每个函数中使用request的时候传入request对象。这两个上下文具体的实现方式和原理可以没必要详细了解
- request:请求上下文上的对象。这个对象一般用来保存一些请求的变量。比如method、args、form等。

- session:请求上下文上的对象。这个对象一般用来保存一些会话信息。(原理与request相似)
- current_app:返回当前的app。
代码部分:
config.py文件
DEBUG = TrueTEMPLATES_AUTO_RELOAD = True
current_app_dome.py文件
from flask import Flask, current_app, render_templateimport configapp_dome = Flask(__name__)app_dome.config.from_object(config)@app_dome.route("/")def home():print(current_app.name)print(current_app.config["TEMPLATES_AUTO_RELOAD"])return render_template('index.html')if __name__ == '__main__':app_dome.run()
返回:
注意点:
1、current_app不能再函数外部进行使用:会报错
# print(current_app.name)# print(current_app.config["TEMPLATES_AUTO_RELOAD"])@app_dome.route("/")def home():return "首页"
2、current_app指代的是当前app这个对象,与你命名的app或者app123无关
3、通过current_app.config[“xxx”]可以获取到现在配置的对应值,但是需要在文件中已经进行配置的
- 可以是通过from_object()进行导入的
- 可以是通过app.config[‘xxx’] = yyy进行写入的
- g:应用上下文上的对象。处理请求时用作临时存储的对象。(所谓临时,就是指在每次刷新页面都会使g对象重置)
g对象能够很好的防止反复传参
现在我们定义了一个工具文件utils.py,其中需要由主入口文件生成的session信息
utils.py文件
def make_name(username):print(username)
主入口文件
from flask import Flask, session, gapp = Flask(__name__)app.config["SECRET_KEY"] = os.urandom(12)app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=1)@app.route("/")def home():name = session['name']g.name = nameprint(make_name(g.name))return "首页"@app.route("/login/")def login():session['name'] = 'gongzhujun'session['password'] = "147258"session.permanent = Truereturn '登录页'if __name__ == '__main__':app.run(debug=True)
虽然这样可以获取的最后的结果,如果需求量大,那会出现反复传参的情况,于是对其进行改造
utils.py文件
from flask import gdef make_name():print(g.name)
主入口文件:
from flask import Flask, session, gfrom utils import make_nameapp = Flask(__name__)app.config["SECRET_KEY"] = os.urandom(12)@app.route("/")def home():name = session['name']password = session['password']g.name = nameg.password = passwordprint(make_name())# 调用自己内部定义的方法getpassword()return "首页"def getpassword():print(g.password)@app.route("/login/")def login():session['name'] = 'gongzhujun'session['password'] = "147258"session.permanent = Truereturn '登录页'if __name__ == '__main__':app.run(debug=True)
返回结果:
在此强调:1、在这个例子中,只有先上传session,g才能获取到对应的值2、g在页面刷新时,会被重置
**
2、钩子函数
1、第一部分-请求前后执行
来一段代码感受一下:
from flask import Flaskapp = Flask(__name__)@app.route("/")def home():print("这是首页")return "首页"@app.before_first_requestdef first_request():print("第一次请求之前")@app.before_requestdef before_request():print("每次请求都被执行")@app.after_requestdef after_request(response):print("每次请求之后被执行")return response@app.teardown_appcontextdef teardown_appcontext(response):print("teardown_appcontext被执行")return responseif __name__ == '__main__':app.run(debug=True)
返回结果:
注意点:
1、如果是在请求之后执行的钩子函数,需要传入response这一参数
2、如果开启debug模式,在页面报错的情况下,请求之后的钩子函数将不会被执行
3、当在次发生请求时,before_first_request将不再被执行
代码解析:
before_first_request:处理第一次请求之前执行:
@app.before_first_requestdef first_request():print("第一次请求之前")
before_request:在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量
@app.before_requestdef before_request():print("每次请求都被执行")
after_request:每次请求之后都被执行(需要注意的是在开启debug模式并且页面报错时将不再执行,如果只是出现异常也会运行,需要传入response)
@app.after_requestdef after_request(response):print("每次请求之后被执行")return response
teardown_appcontext:不管是否有异常,注册的函数都会在每次请求之后执行(同after_request)
@app.teardown_appcontextdef teardown_appcontext(response):print("teardown_appcontext被执行")return response
2、第二部分-定义上下文处理器(context_processor)返回数据到模板中
context_processor:上下文处理器。返回的字典中的键可以在模板上下文中使用
@app.context_processordef context_processor():return {'current_user':'xxx'}
具体应用:
```python from flask import Flask, render_template
app = Flask(name)
@app.context_processor def context(): return { “title1”: “这是首页”, “title2”: “这是登录页” }
@app.route(“/“) def home(): return render_template(“home.html”)
@app.route(“/login/“) def login(): return render_template(“login.html”)
if name == ‘main‘: app.run(debug=True)
login.html```python<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>login</title></head><body><!-- 直接引用title2 -->{{ title2 }}</body></html>
home.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>home</title></head><body><!-- 直接引用title1 -->{{ title1 }}</body></html>
3、第三部分-接收状态码(errorhandler(需要捕获的状态码))
errorhandler接收状态码,可以自定义返回这种状态码的响应的处理方法。
@app.errorhandler(404)def page_not_found(error):return 'This page does not exist',404
捕获异常小例子(为了正常显示关闭debug模式):
from flask import Flask, render_template# 主动抛出异常,让errorhandler进行捕获from flask import abortapp = Flask(__name__)@app.route("/")def home():# 主动抛出400的异常abort(404)return "首页"@app.route("/list/")def list():# 定义一个系统错误,状态码为5001/0return "这是列表页"@app.errorhandler(404)# error是一个形参,必须要写def no_find(error):# 在后面写上400的原因是,使网页中显示的状态码也为404return render_template("404.html"), 404@app.errorhandler(500)def make_error(error):return "服务器内部错误", 500if __name__ == '__main__':app.run(debug=True)
页面显示:
404错误
500错误
代码解读:
主动抛出异常(abort(状态码))
from flask import abort
接收异常的种类:
@app.errorhandler(404)# 不要忘记传入一个形参,一般是errordef no_find(error):# 在后面写上400的原因是,使网页中显示的状态码也为404return render_template("404.html"), 404# return "页面丢失",404

