如何在蓝图中访问app.config?


114

我正在尝试authorisation.py在包api中的蓝图内访问访问应用程序配置。我在初始化的蓝图__init__.py,其在使用authorisation.py

__init__.py

from flask import Blueprint
api_blueprint = Blueprint("xxx.api", __name__, None)
from api import authorisation

authorisation.py

from flask import request, jsonify, current_app

from ..oauth_adapter import OauthAdapter
from api import api_blueprint as api

client_id = current_app.config.get('CLIENT_ID')
client_secret = current_app.config.get('CLIENT_SECRET')
scope = current_app.config.get('SCOPE')
callback = current_app.config.get('CALLBACK')

auth = OauthAdapter(client_id, client_secret, scope, callback)


@api.route('/authorisation_url')
def authorisation_url():
    url = auth.get_authorisation_url()
    return str(url)

我收到RuntimeError:在应用程序上下文之外工作

我知道为什么会这样,但是访问这些配置设置的正确方法是什么?

----更新----暂时,我已经做到了。

@api.route('/authorisation_url')
def authorisation_url():
    client_id, client_secret, scope, callback = config_helper.get_config()
    auth = OauthAdapter(client_id, client_secret, scope, callback)
    url = auth.get_authorisation_url()
    return str(url)

Answers:


133

使用flask.current_app代替app的蓝图视图。

from flask import current_app

@api.route("/info")
def get_account_num():
    num = current_app.config["INFO"]

current_app代理仅仅是在的情况下可要求


25
请注意,current_app代理仅在请求的上下文中可用。
sepehr

1
@sephr关于如何从其他位置访问该请求上下文的任何提示(不将其作为参数传递,而是作为某种全局参数传递)?
carkod

21

重载record方法似乎很容易:

api_blueprint = Blueprint('xxx.api',  __name__, None)
api_blueprint.config = {}

@api_blueprint.record
def record_params(setup_state):
  app = setup_state.app
  api_blueprint.config = dict([(key,value) for (key,value) in app.config.iteritems()])

1
对于Python 3,请使用:app.config.items()而不是app.config.iteritems()
DhoTjai

1
嗨,我是否需要调用或注册record_params,我已经尝试过了,但是没有用。非常感谢。
mrblue

如果您需要访问某个应用程序(例如获取用于设置蓝图的配置),那就太好了!
彼得·拉达

12

为了建立在tbicr的答案上,下面是一个覆盖register方法示例的示例:

from flask import Blueprint

auth = None

class RegisteringExampleBlueprint(Blueprint):
    def register(self, app, options, first_registration=False):
        global auth

        config = app.config
        client_id = config.get('CLIENT_ID')
        client_secret = config.get('CLIENT_SECRET')
        scope = config.get('SCOPE')
        callback = config.get('CALLBACK')

        auth = OauthAdapter(client_id, client_secret, scope, callback)

        super(RegisteringExampleBlueprint,
              self).register(app, options, first_registration)

the_blueprint = RegisteringExampleBlueprint('example', __name__)

以及使用record装饰器的示例:

from flask import Blueprint
from api import api_blueprint as api

auth = None

# Note there's also a record_once decorator
@api.record
def record_auth(setup_state):
    global auth

    config = setup_state.app.config
    client_id = config.get('CLIENT_ID')
    client_secret = config.get('CLIENT_SECRET')
    scope = config.get('SCOPE')
    callback = config.get('CALLBACK')

    auth = OauthAdapter(client_id, client_secret, scope, callback)

“ @ api.record”对我不起作用。“ api”来自哪个命名空间?
蒂姆·理查森

抱歉,我们并未从问题的from api import api_blueprint as api
Kyle James Walker,


4

current_app方法很好,但是您必须具有一些请求上下文。如果您没有(例如一些前期工作,例如测试),那么最好放置

with app.test_request_context('/'):

在这个current_app电话之前。

您将拥有RuntimeError: working outside of application context


3
在工厂中创建该应用程序时,如果因此无法导入“ app”(或任何称为flask应用程序),该怎么办?在请求内部没有问题,因为在请求期间有一个应用程序上下文,但是在请求逻辑之外定义需要应用程序配置的部分时。如果您无法使用应用程序创建上下文,那么该如何访问应用程序配置?
RobertoCuba


3

您要么需要导入appFlask()以下方法返回的主变量(或您所说的任何变量):

from someplace import app
app.config.get('CLIENT_ID')

或在请求中执行此操作:

@api.route('/authorisation_url')
def authorisation_url():
    client_id = current_app.config.get('CLIENT_ID')
    url = auth.get_authorisation_url()
    return str(url)

4
是的,我不想两者都做。第一种是创建交叉引用,第二种方法不是DRY。
Chirdeep Tomar

2
@ChirdeepTomar如果第一种方法是创建循环导入(破坏应用程序),则您的应用程序结构有问题。
丹尼尔·查特菲尔德

13
@DanielChatfield根本不是真的。应用程序对象是注册蓝图的对象。建议导入蓝图是正确的,然后再导入app对象将始终导致循环依赖。请参阅其他答案以获取正确的策略。
sholsapp 2014年

@sholsapp我知道它将创建一个循环导入(就像在flask docs:flask.pocoo.org/docs/patterns/packages中一样),我说过是否创建了一个破坏应用程序的循环导入。
丹尼尔·查特菲尔德,2014年

1

您还可以将蓝图包装在一个函数中,然后将app作为参数传递:

蓝图:

def get_blueprint(app):
    bp = Blueprint()
    return bp

主要:

from . import my_blueprint
app.register_blueprint(my_blueprint.get_blueprint(app))

我尝试了此操作,但是出现了“内部服务器错误”。
MD004

这种方法有什么缺点吗?
Tuukka Mustonen

@Tuukka:我不记得有什么特别的缺点,因为我使用它已经太久了。flask.current_app在多个应用程序中使用蓝图时,使用某些优势。我建议如果这种方法解决了您使用它的问题,那么Flask不会强制执行特定方法。
GeorgSchölly17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.