Как получить доступ к app.config в чертеже?

116

Я пытаюсь получить доступ к конфигурации приложения внутри чертежа, 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)
Чирдип Томар
источник

Ответы:

133

Используйте flask.current_appвместо appв виде чертежа.

from flask import current_app

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

current_appПрокси доступен только в контексте запроса .

Weihuang
источник
25
Обратите внимание, что current_appпрокси доступен только в контексте запроса.
sepehr 06
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()])
Ashalynd
источник
1
Для Python 3 используйте: app.config.items () вместо app.config.iteritems ()
DhoTjai,
1
Привет, мне нужно вызвать или зарегистрировать record_params, я пробовал, но не сработало. Большое спасибо.
mrblue
Если вам нужен доступ к приложению (например, получить конфигурацию для НАСТРОЙКИ чертежа), это прекрасно!
Питер Лада,
13

Чтобы опираться на ответ 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
Кайл Джеймс Уокер
4

current_appПодход хорошо , но вы должны иметь некоторый контекст запроса. Если у вас его нет (некоторые предварительные работы, например, тестирование), вам лучше разместить

with app.test_request_context('/'):

перед этим current_appзвонком.

RuntimeError: working outside of application contextВместо этого у вас будет .

Бен Усман
источник
3
А что насчет того, когда приложение создается на фабрике и, следовательно, «приложение» (или как там называется приложение-фляга) недоступно для импорта? Внутри запросов это не проблема, потому что во время запросов есть контекст приложения, но при определении частей вне логики запроса, требующих конфигурации приложения. как можно получить доступ к конфигурации приложения, если вы не можете использовать приложение для создания контекста?
RobertoCuba
3

Вам либо нужно импортировать основную appпеременную (или как вы ее назвали), возвращаемую Flask():

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
Да, я не хотел делать ни то, ни другое. Первый - это создание перекрестных ссылок, а второй подход - НЕ СУХОЙ.
Чирдип Томар
2
@ChirdeepTomar Если первый подход заключается в создании циклического импорта (который нарушает работу приложения), то что-то не так со структурой вашего приложения.
Дэниел Чатфилд,
13
@DanielChatfield, это просто неправда. Объект приложения - это объект, который регистрирует чертежи. Если предположить, что это правильно для чертежа, то импорт объекта приложения всегда будет вызывать циклическую зависимость. См. Другие ответы для правильной стратегии.
sholsapp 04
@sholsapp Я знаю, что он создаст циклический импорт (точно так же, как это делается в документации по фляжке: flask.pocoo.org/docs/patterns/packages ), я сказал, если он создает циклический импорт, который сломает приложение .
Дэниел Чатфилд
1

Вы также можете обернуть план в функцию и передать app качестве аргумента:

Чертеж:

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

Основной:

from . import my_blueprint
app.register_blueprint(my_blueprint.get_blueprint(app))
Георг Шёлли
источник
Я пробовал это, но у меня возникла «Внутренняя ошибка сервера».
MD004
Есть ли у этого подхода недостатки?
Туукка Мустонен
@Tuukka: Особых недостатков не помню, давно уже не пользовался. flask.current_appИспользование схемы в нескольких приложениях может дать некоторые преимущества . Я бы посоветовал, если этот подход решит ваши проблемы, использовать его, Flask не применяет конкретный подход.
Георг Шелли