前言
最近學習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語句中的進行操作,但是這是不太現實的,所以需要手動的去調節。
后記
經過這么一番的折騰,總結學東西還是要多查資料,多堅持一會,也許今天困擾你的東西,明天就豁然開朗了。