【问题标题】:current_app and importing config settings in Flaskcurrent_app 和在 Flask 中导入配置设置
【发布时间】:2016-01-02 19:21:01
【问题描述】:

最近,我开始使用 Flask 构建应用程序。它非常易于使用,但功能强大且使用起来很有趣。不幸的是,我在理解应用程序上下文的工作方式时遇到了问题。我知道 current_appapp_context 以及 current_app 引用应该在请求中使用,但这可能是我的问题的一部分。

我正在构建一个具有以下文件夹结构的应用程序:

app/
     main/
         __init__.py
         error.py
         forms.py
         routes.py
     static/
     templates/
     __init__.py
     email.py
     models.py
config.py
run.py

我在routes.py 中执行from flask import current_app 来导入配置设置,它按预期工作。

但是当我在forms.py 中导入 current_app 时,我可以做任何我想做的事,但我总是收到这个错误:

Traceback (most recent call last):
  File "./run.py", line 6, in <module>
    app = create_app('development')
  File "/home/letmecode/Projects/python/flask/folder/app/__init__.py", line 34, in create_app
    from main import main as main_blueprint
  File "/home/letmecode/Projects/python/flask/folder/app/main/__init__.py", line 5, in <module>
    from . import routes, errors, forms
  File "/home/letmecode/Projects/python/flask/folder/app/main/routes.py", line 8, in <module>
    from .forms import (ChangePasswordForm, ChangeEmailForm, CreateItemForm, RetrievePasswordForm, LoginForm,
  File "/home/letmecode/Projects/python/flask/folder/app/main/forms.py", line 132, in <module>
    class CreateItemForm(Form):
  File "/home/letmecode/Projects/python/flask/folder/app/main/forms.py", line 133, in CreateItemForm
    print current_app
  File "/home/letmecode/.virtualenvs/folder/local/lib/python2.7/site-packages/werkzeug/local.py", line 362, in <lambda>
    __str__ = lambda x: str(x._get_current_object())
  File "/home/letmecode/.virtualenvs/folder/local/lib/python2.7/site-packages/werkzeug/local.py", line 302, in _get_current_object
    return self.__local()
  File "/home/letmecode/.virtualenvs/folder/local/lib/python2.7/site-packages/flask/globals.py", line 34, in _find_app
    raise RuntimeError('working outside of application context')
RuntimeError: working outside of application context

forms.py 只是一个包含flask-wtf 表单类和验证器函数的模块。

我的问题是,我想在其中引用应用上下文,以便获取在整个应用中使用的设置。

我在这里做错了什么?我猜forms.py 内部发生的事情不是请求的一部分,因此会以某种方式失败。但是我还应该如何引用应用上下文呢?

编辑:

#forms.py

from flask import current_app

#[...]

class CreateItemForm(Form):
    title = TextField('Title', [
        validators.Length(min=3, max=140),
        validators.Regexp('^[a-zA-Z][a-zA-Z0-9 ]+$', 0, 'Item titles must start with a letter and consist of numbers and letters, only')
    ])
    description = TextAreaField('Description', [
        validators.Length(min=3, max=1000),
    ])
    tags = TextField('Tags')
    branch = SelectField(
        'Branch',
        choices=current_app.config['BRANCHES']
    )

【问题讨论】:

  • 请发布您的 CreateItemForm 类...基本上将 current_app 移动到该方法中,而不是在类级别
  • 已更新。抱歉,我忘记了。

标签: python flask wtforms


【解决方案1】:

根本问题是CreateItemForm 和所有属性都是在第一次导入forms 模块时创建的。这意味着每当运行import .form 时都会创建branch 字段,因此随后会访问current_app

# app/main/routes.py
from .forms import ( ..., CreateItemForm, ...)

查看您的堆栈跟踪,这发生在您的 create_app 调用中 - 很可能,您的 create_app 看起来像这样:

def create_app(config_name):
    app = Flask('some-name-here')
    app.config.from_SOMETHING(config_name)

    # Register things here
    from main import main as main_blueprint

    app.register_blueprint(...)

    return app

# Register things here,您可以简单地创建一个app_context 并导入其中的所有内容:

# Register things here
# Creating an explicit application context to allow
# easy access to current_app.config, etc.
with app.app_context():
    from main import main as main_blueprint
    app.register_blueprint(...)

return app

【讨论】:

  • 就是这样!我完全误解了app_context 的工作原理并错误地使用了它,这就是我没有让它工作的原因。谢谢!
【解决方案2】:

我发现我是个白痴。您不必为每个表单模型提供选择。您可以(并且应该)通过视图/路由功能提供它们,例如:

form.select_field.choices = [('value1', 'label1'), ('value2', 'label2')]

这并没有明确回答我的问题,但使它有些过时了。但是,我不会接受我自己的答案作为解决方案(还),因为我很好奇在这种情况下是否可以通过 app/current_app 导入配置选项,而不会变得笨拙。如果我的好奇心不能满足,我会接受我自己的答案。

我希望 wtforms/flask-wtf 文档少关注明显的,多关注不那么明显的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2017-03-09
    • 1970-01-01
    • 2017-05-28
    • 2017-04-30
    相关资源
    最近更新 更多