flask RuntimeError: Working outside of application context 问题解决
前言
最近学习flask
表单的时候,碰到了一个问题,看着教程百思不得其解,所以查阅了一些资料的终于把这个困扰了我两个晚上的问题解决了。
问题详情
在教程中的是这样写的:
(venv) D:\VScode\helloflask>flask shell Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32 App: app [production] Instance: D:\VScode\helloflask\instance >>> from flask_wtf import FlaskForm >>> from wtforms import StringField,PasswordField, BooleanField,SubmitField >>> from wtforms.validators import DataRequired,Length >>> >>> class LoginForms(FlaskForm): ... username = StringField('Username', validators=[DataRequired()]) ... password = PasswordField('Password', validators=[DataRequired(),Length(8,128)]) ... remember = BooleanField('Remember me') ... submit = SubmitField('Log in') ... >>> login = LoginForms()
但是这样写之后,却发现报错了:
Traceback (most recent call last): File "<console>", line 1, in <module> File "d:\vscode\helloflask\venv\lib\site-packages\wtforms\form.py", line 208, in __call__ return type.__call__(cls, *args, **kwargs) File "d:\vscode\helloflask\venv\lib\site-packages\flask_wtf\form.py", line 87, in __init__ super(FlaskForm, self).__init__(formdata=formdata, **kwargs) File "d:\vscode\helloflask\venv\lib\site-packages\wtforms\form.py", line 274, in __init__ self.process(formdata, obj, data=data, **kwargs) File "d:\vscode\helloflask\venv\lib\site-packages\wtforms\form.py", line 131, in process field.process(formdata) File "d:\vscode\helloflask\venv\lib\site-packages\wtforms\csrf\core.py", line 43, in process self.current_token = self.csrf_impl.generate_csrf_token(self) File "d:\vscode\helloflask\venv\lib\site-packages\flask_wtf\csrf.py", line 141, in generate_csrf_token token_key=self.meta.csrf_field_name File "d:\vscode\helloflask\venv\lib\site-packages\flask_wtf\csrf.py", line 45, in generate_csrf if field_name not in session: File "d:\vscode\helloflask\venv\lib\site-packages\werkzeug\local.py", line 379, in <lambda> __contains__ = lambda x, i: i in x._get_current_object() File "d:\vscode\helloflask\venv\lib\site-packages\werkzeug\local.py", line 306, in _get_current_object return self.__local() File "d:\vscode\helloflask\venv\lib\site-packages\flask\globals.py", line 38, in _lookup_req_object raise RuntimeError(_request_ctx_err_msg) RuntimeError: Working outside of request context. This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.
作为小白的我看的是一脸懵逼啊。完全不知道出了什么问题。翻译了一下大致的意思就是你需要一个活动的HTTP请求,可是我该怎么办呢。
然后我又尝试了一种办法,把上面这个问题我们记为问题1
吧
(venv) D:\VScode\helloflask>ipython Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] Type 'copyright', 'credits' or 'license' for more information IPython 7.18.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: from flask_wtf import FlaskForm ...: from wtforms import StringField,PasswordField, BooleanField,SubmitField ...: from wtforms.validators import DataRequired,Length ...: ...: class LoginForms(FlaskForm): ...: username = StringField('Username', validators=[DataRequired()]) ...: password = PasswordField('Password', validators=[DataRequired(),Length(8,128)]) ...: remember = BooleanField('Remember me') ...: submit = SubmitField('Log in') ...: In [2]: forms = LoginForms()
但是又报错了。
RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve this, set up an application context with app.app_context(). See the documentation for more information.
意思就是没有在应用的上下文中。到这里我已经不知道怎么办了。。欲哭无泪,但是我们还是把这个问题记为问题2
吧,总归是要解决的
解决问题
但是我没有放弃尝试和查找资料该如何解决,经过我2天下班后的不断折腾,终于在一个论坛中看见了一个和我一样的问题。
并且看到了其中一个回复:
看到后觉得如获至宝,就立马去flask shell
中尝试了一下:
(venv) D:\VScode\helloflask>flask shell Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32 App: app [production] Instance: D:\VScode\helloflask\instance >>> from flask_wtf import FlaskForm >>> from wtforms import StringField,PasswordField, BooleanField,SubmitField >>> from wtforms.validators import DataRequired,Length >>> >>> class LoginForms(FlaskForm): ... username = StringField('Username', validators=[DataRequired()]) ... password = PasswordField('Password', validators=[DataRequired(),Length(8,128)]) ... remember = BooleanField('Remember me') ... submit = SubmitField('Log in') ... >>> with app.test_request_context(): ... form = LoginForms() ... >>> form.username() Markup('<input id="username" name="username" required type="text" value="">') >>>
多谢这位大佬的指点,那么问题1
到这里就算是解决了。但是问题2还没有解决,为此我决定去看看这个上下文的东西。
终于解决了困扰了2天的问题:
(venv) D:\VScode\helloflask>ipython Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] Type 'copyright', 'credits' or 'license' for more information IPython 7.18.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: from app import app In [2]: from flask import current_app In [3]: app_ctx = app.app_context() In [4]: app_ctx.push() In [5]: from flask_wtf import FlaskForm ...: from wtforms import StringField,PasswordField, BooleanField,SubmitField ...: from wtforms.validators import DataRequired,Length ...: ...: class LoginForms(FlaskForm): ...: username = StringField('Username', validators=[DataRequired()]) ...: password = PasswordField('Password', validators=[DataRequired(),Length(8,128)]) ...: remember = BooleanField('Remember me') ...: submit = SubmitField('Log in') ...: In [6]: with app.test_request_context(): ...: form = LoginForms() ...: In [7]: form.username() Out[8]: Markup('<input id="username" name="username" required type="text" value="">') In [9]:
问题总结
问题1
首先在问题1中我们使用了flask shell
的方式进入shell,根据教程中的解释,在使用flask shell的时候自动会进入应用上下文情境。但是我们创建forms表单,没有使用的app.test_request_context():
进入请求的上下文情境,所以导致运行报错没有活动的HTTP请求。因为初始化就没有在请求的情境中。
问题2
第二次我没有使用flask shell
的方式进入shell,然后运行报错set up an application context with app.app_context(),因为我进入的是python的shell并没有进入flask的shell,所以报错了。然后我们根据查的资料的手动推送一下应用的上下文情境,然后在进行请求的情境,这样我们的代码执行就没有错误了。至于为什么不用 with app.app_context() ,因为在with语句外面,我们这个情境已经被释放了。所以运行就会继续报第二个问题的错误了。除非我们全部在with语句中的进行操作,但是这是不太现实的,所以需要手动的去调节。
后记
经过这么一番的折腾,总结学东西还是要多查资料,多坚持一会,也许今天困扰你的东西,明天就豁然开朗了。
随风挥手 ——土木狗的IT生涯 | 群: 299524235 |