Як отримати доступ до 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

autisation.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Проксі доступний тільки в контексті запиту .


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
Кайл Джеймс Уокер


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
Так, я не хотів робити жодного з двох. Перший - це створення перехресних посилань, а другий - не ДУХА.
Chirdeep Tomar

2
@ChirdeepTomar Якщо перший підхід - це круговий імпорт (який порушує програму), то в структурі вашого додатка щось не так.
Даніель Чатфілд

13
@DanielChatfield це просто неправда. Об'єкт програми - це об'єкт, який реєструє креслення. Якщо припустити, що це правильно для креслення, то імпортувати об’єкт програми завжди буде викликати кругову залежність. Дивіться інші відповіді щодо правильної стратегії.
sholsapp

@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 не застосовує конкретного підходу.
Георг Шоллі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.