Flask Jinja2模板中session无法调用的问题排查求助
问题:Flask模板中
session未定义,无法访问session.yesOrNo 我搭建了一个小型测试项目,预期首次访问页面时显示"maybe",之后能将值存入session并在模板中使用。
项目结构
$ find * | grep -v __ app.py pages pages/app_main.html requirements.txt
app.py代码
import sys from dotenv import dotenv_values from flask import Flask, session from jinja2 import Environment, PackageLoader cfg = dotenv_values(".env") sys.path.append(f"{cfg['APP_HOME']}") app = Flask(__name__) app.config["SESSION_TYPE"] = "filesystem" app.secret_key = b'aae14431-9269-4322-958e-7dbb4474bf7a' application = app env = Environment(loader=PackageLoader('app', 'pages')) @app.route("/") def app_main(): main = env.get_template('app_main.html') session['yesOrNo'] = 'maybe' context = dict() print(f"the yesOrNo value is {session.get('yesOrNo')}") return main.render(**context) @app.route("/setyes") def app_yes(): main = env.get_template('app_main.html') session['yesOrNo'] = 'yes' context = dict() return main.render(**context) @app.route("/setno") def app_no(): main = env.get_template('app_main.html') session['yesOrNo'] = 'no' context = dict() return main.render(**context) if __name__ == '__main__': app.run()
模板文件pages/app_main.html代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <html> <head> <title>App</title> </head> <body> <div> <p>{{ session.yesOrNo }}</p> </div> </body></html>
报错信息
* Detected change in '/home/ray/Projects/test_session/app.py', reloading * Restarting with stat * Debugger is active! * Debugger PIN: 978-769-374 the yesOrNo value is maybe 127.0.0.1 - - [26/Apr/2023 14:27:08] "GET / HTTP/1.1" 500 - Traceback (most recent call last): File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 2548, in __call__ return self.wsgi_app(environ, start_response) File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app response = self.handle_exception(e) File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 2525, in wsgi_app response = self.full_dispatch_request() File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 1822, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 1820, in full_dispatch_request rv = self.dispatch_request() File "/home/ray/.local/lib/python3.10/site-packages/flask/app.py", line 1796, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "/home/ray/Projects/test_session/app.py", line 25, in app_main return main.render(**context) File "/home/ray/.local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render self.environment.handle_exception() File "/home/ray/.local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception raise rewrite_traceback_stack(source=source) File "/home/ray/Projects/test_session/pages/app_main.html", line 8, in top-level template code <p>{{ session.yesOrNo }}</p> File "/home/ray/.local/lib/python3.10/site-packages/jinja2/environment.py", line 485, in getattr return getattr(obj, attribute) jinja2.exceptions.UndefinedError: 'session' is undefined
解答
问题出在你手动初始化了Jinja2的Environment和PackageLoader,这种方式没有把Flask的上下文(比如session对象)注入到模板环境中。Flask自带的render_template函数会自动处理上下文传递,包括session、request等内置对象。
修改方案如下:
- 删掉手动创建的Jinja环境相关代码,导入Flask的
render_template - 视图函数中改用
render_template渲染模板,不需要手动获取模板再调用render - 确保模板文件夹路径符合Flask规则,要么改名为默认的
templates,要么在Flask初始化时指定template_folder参数
修改后的app.py代码:
import sys from dotenv import dotenv_values from flask import Flask, session, render_template # 导入render_template cfg = dotenv_values(".env") sys.path.append(f"{cfg['APP_HOME']}") # 指定模板文件夹为pages app = Flask(__name__, template_folder='pages') app.config["SESSION_TYPE"] = "filesystem" app.secret_key = b'aae14431-9269-4322-958e-7dbb4474bf7a' application = app # 移除手动创建Jinja环境的代码 # env = Environment(loader=PackageLoader('app', 'pages')) @app.route("/") def app_main(): session['yesOrNo'] = 'maybe' print(f"the yesOrNo value is {session.get('yesOrNo')}") return render_template('app_main.html') # 改用render_template @app.route("/setyes") def app_yes(): session['yesOrNo'] = 'yes' return render_template('app_main.html') @app.route("/setno") def app_no(): session['yesOrNo'] = 'no' return render_template('app_main.html') if __name__ == '__main__': app.run()
这样修改后,模板里的{{ session.yesOrNo }}就能正常访问session中的值了。
内容的提问来源于stack exchange,提问作者Ray Kiddy
相关产品推荐
相关产品推荐

