我对Flask是陌生的,只编写了一个相当简单的Web应用程序-没有数据库,只是一个航班搜索API的前端。一切正常,但是为了提高技能,我试图通过应用程序工厂和蓝图来重构代码。使它可以与push()
一起使用,但是无法使with
块正常工作。
fly_app/__init.py__
我的原始代码:
from flask import Flask
from config import Config
import logging
from logging.handlers import RotatingFileHandler
import os
app = Flask(__name__)
app.config.from_object(Config)
if not app.debug:
...
from fly_app import routes, errors # noqa
我根据需要将应用程序导入了其他模块。
现在,该文件已被重构为此,并且似乎可以正常工作:
from flask import Flask
import logging
from logging.handlers import RotatingFileHandler
import os
def create_app():
# create and configure the app
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY=os.environ.get('SECRET_KEY', 'nice-try')
)
app.app_context().push()
if not app.debug and not app.testing:
...
from . import routes
app.register_blueprint(routes.bp)
return app
我需要app_context,因此可以在其他模块中使用current_app.static_folder和current_app.logger.exception()。我已经读过使用with
块,例如
with app.app_context():
init_db()
优于
app.app_context().push()
从Flask文档中:“在with块中使用app_context(),并且该块中运行的所有内容都可以访问current_app。”
我的问题:
with
区块相比,app.app_context().push()
区块有何不同或更好?
push()
?app
是否等于使with
成为我的原始代码中的全局变量,从而什么也没做?with
块正常工作。我尝试了app.static_folder
块,包括:
current_app
current_app.[attr]
(导入后)或flask_wtf.FlaskForm
例如,我编写了两个自定义验证器-code_check和currency_check-以与forms.py
模块中从form
派生的类一起使用。这些带有field
和Bundler could not find compatible versions for gem "actionpack":
In Gemfile:
jquery-datatables-rails x64-mingw32 was resolved to 3.4.0, which depends on
actionpack (>= 3.1) x64-mingw32
rails (= 5.2.3) x64-mingw32 was resolved to 5.2.3, which depends on
actionpack (= 5.2.3) x64-mingw32
rspec-rails x64-mingw32 was resolved to 3.8.2, which depends on
actionpack (>= 3.0) x64-mingw32
simple_form x64-mingw32 was resolved to 4.1.0, which depends on
actionpack (>= 5.0) x64-mingw32
rails (= 5.2.3) x64-mingw32 was resolved to 5.2.3, which depends on
sprockets-rails (>= 2.0.0) x64-mingw32 was resolved to 3.2.1, which
depends on
actionpack (>= 4.0) x64-mingw32
位置参数,由于它们未定义,我无法将它们放在with块中。
作为一个相对较新的人,尽管阅读了文档并搜索了互联网,但我显然不了解应用程序上下文的工作原理。
答案 0 :(得分:0)
当Flask推出新产品时,将来自多个源的代码拼凑在一起是令人沮丧的秘诀。我知道了您的前进方向,并强烈建议您通读Miguel Grinberg的Flask Mega Tutorial。它提供了一条路径,可以使您更好地了解Flask的工作方式。
(提示:app.app_context().push()
中不需要create_app()
)
答案 1 :(得分:0)
我认为我可以完全回答我的上述三部分问题。首先,第三部分-在with
块中放置什么。答案很简单:
fly_app.__init__.py
from flask import Flask
...
def create_app():
...
with app.app_context():
from . import routes
app.register_blueprint(routes.bp)
return app
我要做的只是将蓝图注册放入with
块中。在那之后一切似乎都正常了。 (最终,我决定不朝那个方向前进(如下所述)。
关于第1部分和第2部分-with
块与push()
有何不同?push()
是否赋予对应用程序上下文的全局访问权限?我不确定这些答案,但是在口译员中玩耍给了我一些见解。当我在app.app_context().push()
函数中使用create_app()
时:
>>> import fly_app
>>> from flask import current_app
>>> current_app
<LocalProxy unbound>
>>> fly_app.create_app()
<Flask 'fly_app'>
>>> current_app
<Flask 'fly_app'>
>>> current_app.static_folder
'/Users/Steve/.../fly_app/static'
current_app
及其属性立即可用。但是,如果我使用with
块来导入和注册routes.bp
,则会得到不同的结果。 current_app
没有公开绑定或可用:
>>> import fly_app
>>> from flask import current_app
>>> current_app
<LocalProxy unbound>
>>> fly_app.create_app()
<Flask 'fly_app'>
>>> current_app
<LocalProxy unbound>
>>> fly_app.routes.current_app.static_folder
Traceback (most recent call last):
...
RuntimeError: Working outside of application context.
但是code_dir = os.path.join(current_app.static_folder, 'JSON/optd_codes.json')
仍然有效:
>>> fly_app.routes.code_dir
'/Users/Steve/Documents/flask_requests_env/dragonfly/fly_app/static/JSON/optd_codes.json'
因此,我从这些观察中得出的结论是,app.app_context().push()
似乎确实使应用程序上下文全局可用,但是使用with
块却没有。或在我的非CS解释中,应用程序上下文可用,但范围更窄,即仅适用于我的应用程序的指定部分。
最终,由于大卫·史密斯(David W. Smith)的指导(请参阅他的回答以及我和他的谈话中的注释),我决定需要一个指向静态文件夹的路径并不是手动推送应用程序上下文的一个好理由。我为static_folder
使用了Blueprint
关键字参数,并将current_app.static_folder
替换为bp.static_folder
。无需手动推送。