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語句中的進行操作,但是這是不太現實的,所以需要手動的去調節。

后記

經過這么一番的折騰,總結學東西還是要多查資料,多堅持一會,也許今天困擾你的東西,明天就豁然開朗了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM