Flask学习笔记(十五)-Flask 上下文详解
一、上下文说明
上下文:在程序中可以理解为在代码执行到某一时刻时,根据之前代码所做的操作以及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以完成的事情。
Flask中有两种上下文,请求上下文和应用上下文
Flask中上下文对象:相当于一个容器,保存了 Flask 程序运行过程中的一些信息。
1、请求上下文
思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session
request:
封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get(‘user’),获取的是get请求的参数。
session:
用来记录请求会话中的信息,针对的是用户信息。举例:session[‘name’] = user.id,可以记录用户信息。还可以通过session.get(‘name’)获取用户信息。
2、应用上下文
它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
应用上下文对象有:current_app,g
current_app:
应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量
g
:
应用上下文上的对象。这个对象一般是处理请求时用作临时存储的对象。
二、案例详解
项目目录:
----app1.py
----utils.py
----utils1.py
1、通过session会话实现
app1.py文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import os from flask import Flask, current_app,session,g from flask_sqlalchemy import SQLAlchemy from utils import log_a,log_b from utils1 import log_a,log_b db = SQLAlchemy() app1 = Flask(__name__) app1.config[ 'SECRET_KEY' ] = os.urandom( 14 ) @app1 .route( "/login" ) def login(): return "登录页面" # 不能写在视图函数外面 # print(current_app.name) @app1 .route( "/" ) def index(): # 获取当前文件名 print(current_app.name) # 获取当前文件配置的一些属性 print(current_app.config[ 'SECRET_KEY' ]) return "这是首页" #设置默认session @app1 .route( "/set_session" ) def set_session(): session[ "username" ] = "xiaoming" return "设置session成功" + session[ "username" ] @app1 .route( "/index1" ) def index1(): username = session.get( 'username' ) log_a(username) log_b(username) return "这是index1" |
创建一个工具文件 utils.py,进一步理解 “所有请求共享全局变量 current_app”
1 2 3 4 5 | def log_a(username): print( "log a %s" % username) def log_b(username): print( "log b %s" % username) |
运行结果:
2、使用 g 对象实现
app1.py文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import os from flask import Flask, current_app,session,g from flask_sqlalchemy import SQLAlchemy from utils1 import log_a,log_b db = SQLAlchemy() app1 = Flask(__name__) app1.config[ 'SECRET_KEY' ] = os.urandom( 14 ) @app1 .route( "/login" ) def login(): return "登录页面" # 不能写在视图函数外面 # print(current_app.name) @app1 .route( "/" ) def index(): # 获取当前文件名 print(current_app.name) # 获取当前文件配置的一些属性 print(current_app.config[ 'SECRET_KEY' ]) return "这是首页" #设置默认session @app1 .route( "/set_session" ) def set_session(): session[ "username" ] = "xiaoming" return "设置session成功" + session[ "username" ] @app1 .route( "/index2" ) def index2(): username=session.get( 'username' ) g.username=username # 不需传参 log_a() log_b() return "这是index2" if __name__ == '__main__' : app1.run() |
创建一个工具文件 utils1.py
1 2 3 4 5 6 7 | from flask import g # 不需参数 def log_a(): print( "log a %s" % g.username) def log_b(): print( "log b %s" % g.username) |
运行结果:
三、常用的钩子函数
3.1、before_first_request
1 2 3 4 5 | # 处理第一次请求之前执行 @app .before_first_request def first_request(): print '这是第一次请求之前执行的' |
3.2、before_request
1 2 3 4 5 6 7 8 | # 在每次请求之前执行. 通常可以用这个装饰器来给视图函数增加一些变量 @app .before_request def handel_before(): if not hasattr(g, 'user' ): setattr(g, 'user' , 'xxxx' ) print( "每次请求之前被执行的" ) |
3.3、after_request
1 2 3 4 5 6 7 8 | # 每次请求之后被执行的 # 这里注意, 需要传入参数(response 这个形参名字可以改) # 因为是请求完成后执行, 自然就有响应返回 @app .after_request def handel_after(response): print( "每次请求之后被执行的" ) return response |
3.4、teardown_appcontext
1 2 3 4 5 6 7 | # 不管是否有异常, 注册的函数都会在每次请求之后执行 # 同理, 应传入参数(response 这个形参名字可以改) @app .teardown_appcontext def handel_teardowm(response): print( "handel_teardowm 被执行" ) return response |
3.5、context_processor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 上下文处理器. 返回的字典中的键可以在模板上下文中使用 def index(): return render_template( "index.html" ) # 不使用 context_processor, 则需要在后面添加 # return render_template( "index.html" , username= 'check' ) @app .route( "/list" ) def list(): return render_template( "list.html" ) # 每个还是都要添加 # return render_template( "list.html" , username= 'check' ) # 当需要向多个 html 页面传输数据时, 使用该函数更方便 @app .context_processor def context(): return { "username" : "check" } |
3.6、errorhandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # errorhandler 接收状态码, 可以自定义返回这种状态码的响应的处理方法 @app .errorhandler( 404 ) def page_not_find(error): # return render_template( "404.html" ), 404 return "页面不存在" , 404 @app .errorhandler( 500 ) def server_error(error): return "服务器内部错误..." , 500 @app .route( "/" ) def index(): # 主动抛出 404 异常, 使得访问首页时显示 "页面不存在" abort( 404 ) print( "这是首页" ) return render_template( "index.html" ) |
本文来自博客园,作者:橘子偏爱橙子,转载请注明原文链接:https://www.cnblogs.com/xfbk/p/16822450.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?