Flask应用程序上下文:app.app_Context().push()可以工作,但可以';“得不到”;使用app.app_context();阻止工作

Flask应用程序上下文:app.app_Context().push()可以工作,但可以';“得不到”;使用app.app_context();阻止工作,flask,Flask,我是flask的新手,只编写了一个相当简单的web应用程序——没有db,只是一个航班搜索API的前端。这一切都很好,但为了提高我的技能,我正试图用一个应用程序工厂和蓝图来重新考虑我的代码。已使其与push()一起工作,但无法使与块一起工作 fly_app/__init.py__ 我的原始代码: from flask import Flask from config import Config import logging from logging.handlers import Rotatin

我是flask的新手,只编写了一个相当简单的web应用程序——没有db,只是一个航班搜索API的前端。这一切都很好,但为了提高我的技能,我正试图用一个应用程序工厂和蓝图来重新考虑我的代码。已使其与
push()
一起工作,但无法使
块一起工作

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\u上下文,以便在其他模块中使用当前的\u app.static\u文件夹和当前的\u app.logger.exception()。我已经读到使用带有块的
,例如

with app.app_context():
    init_db()
优先于

app.app_context().push()
来自Flask文档:“在with块中使用app_context(),块中运行的所有内容都可以访问当前的app_应用。”

我的问题是:

  • 使用
  • 块的
    与使用不同或更好吗
    
    app.app\u context().push()
  • 使用
    push()
  • 我不知道如何使
    with
    块在不引发“RuntimeError:在应用程序上下文之外工作”的情况下工作。我已尝试了
    with
    块,包括:
    • app.static\u文件夹
    • 当前应用程序
      (导入后)或
      当前应用程序。[attr]
    • 使用当前应用程序的特定module.methods()或属性
  • 例如,我编写了两个自定义验证器--code_check和currency_check--用于
    forms.py
    模块中派生自
    flask_wtf.FlaskForm
    的类。它们采用
    形式
    字段
    位置参数,我无法将它们放入with块中,因为它们未定义


    作为一个相对的新手,我显然不了解应用程序上下文是如何工作的,尽管我阅读了文档并在互联网上搜索。

    在Flask上使用新代码时,从多个来源拼凑代码会让我感到沮丧。我知道你的方向,强烈建议你通读米格尔·格林伯格的书。它列出了一条路径,可以让您更好地了解烧瓶是如何工作的


    (提示:在
    create\u app()
    中没有必要使用
    app.app\u context().push()

    我想我可以充分回答上面的三部分问题。首先,第三部分——使用
    块在
    中放置什么。这个答案非常简单:

    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部分--
    块的
    push()
    有何不同,以及
    push()
    是否授予对应用程序上下文的全局访问权限?我不确定这些答案,但在解释器中玩游戏给了我一些见解。当我在
    创建应用程序()中使用
    app.app\u context().push()
    功能:

    >>> 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'
    
    但是
    code\u dir=os.path.join(当前的\u app.static\u文件夹'JSON/optd\u 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()
    似乎确实使应用程序上下文全局可用,但将
    块一起使用则不可用。或者在我的非CS解释中,应用程序上下文可用,但范围更窄,即仅适用于我的应用程序的指定部分


    最后,感谢David W.Smith的指导(见他的答案和我在评论中与他的对话),我决定需要静态文件夹的路径不是手动推送应用程序上下文的好理由。我使用
    静态文件夹
    关键字参数作为我的
    蓝图
    ,并将
    当前应用程序.static文件夹
    替换为
    bp.static\u文件夹
    。无需手动推送。

    谢谢。我第一次学习了Flask与Miguel的教程,但从来没有完成它,因为我有所有的东西,我需要让我的简单的飞行搜索应用程序工作。现在作为一个学习经验,我试图重新考虑我的代码使用应用工厂。我通过了Flask的。我还回到了Miguel的教程,第十五部分,一个更好的应用程序结构。他创建了inst在他的应用程序工厂中,他调用instance.init_app(app)。这似乎与我的情况无关。如果我不推()我会得到上下文错误。你需要
    app.app_context().push()
    (或者
    和app.app_context():…
    ,只要你需要随应用程序一起配置的东西(如
    db
    ,这取决于
    db.init_app(app)
    对其进行配置),或者您需要执行Flask期望请求上下文执行的操作。在
    create_app()中执行此操作
    使Flask机器处于异常状态,可能会在其他地方给您带来神秘的问题。再次感谢。我想您是说,如果可以避免,最好不要手动推送应用程序上下文。Flask文档中写道:“Flask在处理请求时自动推送应用程序上下文。”但我觉得我需要为一个简单的任务推送应用程序上下文,在请求之外定义JSON文件的路径,例如:
    code\u dir=os.path.join(当前的\u app.static\u文件夹,'JSON/optd\u codes.JSON')
    ,所以我通过设置:
    bp=Blueprint('routes',\u name\u,static\u folder='./static'找到了解决方法
    code\u dir=os.path.join(bp.static\u folder,'JSON/optd\u codes.JSON')
    更好?这看起来更好。您仍然需要应用程序上下文来处理请求上下文之外的内容(例如,单元测试和cli内容),但获取(推送)这个上下文尽可能接近你所需要的东西,这会让你省去调试的痛苦
    >>> fly_app.routes.code_dir
    '/Users/Steve/Documents/flask_requests_env/dragonfly/fly_app/static/JSON/optd_codes.json'