Wie greife ich in einer Blaupause auf app.config zu?


114

Ich versuche, auf die Konfiguration der Zugriffsanwendung innerhalb eines Entwurfs zuzugreifen, authorisation.pyder in einer Paket-API enthalten ist. Ich initialisiere die Blaupause, in __init__.pyder in verwendet wird 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)

Ich erhalte RuntimeError: Arbeiten außerhalb des Anwendungskontexts

Ich verstehe, warum das so ist, aber wie kann man dann richtig auf diese Konfigurationseinstellungen zugreifen?

---- Update ---- Vorübergehend habe ich das getan.

@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)

Antworten:


131

Verwenden Sie flask.current_appanstelle von appin der Blaupausenansicht.

from flask import current_app

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

Der current_appProxy ist nur im Rahmen einer Anfrage verfügbar .


25
Beachten Sie, dass der current_appProxy nur im Kontext einer Anforderung verfügbar ist.
— September

1
@sephr Gibt es Tipps, wie Sie von anderen Stellen aus auf diesen Anforderungskontext zugreifen können (ohne ihn als Parameter, aber als eine Art globalen Parameter zu übergeben)?
— Carkod

21

Die Überladungsmethode recordscheint recht einfach zu sein:

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
Für Python 3 verwenden Sie: app.config.items () anstelle von app.config.iteritems ()
— DhoTjai

1
Hallo, muss ich record_params aufrufen oder registrieren? Ich habe es versucht, aber es hat nicht funktioniert. Vielen Dank.
— Mrblue

Wenn Sie Zugriff auf eine App benötigen (z. B. die Konfiguration zum Einrichten der Blaupause), ist dies großartig!
— Peter Lada

12

Um auf der Antwort von tbicr aufzubauen , ist hier ein Beispiel, das das registerMethodenbeispiel überschreibt :

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__)

Und ein Beispiel mit dem recordDekorateur :

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' funktioniert bei mir nicht ,. Aus welchem ​​Namespace stammt 'api'?
— Tim Richardson

Sorry, habe das nicht aus der Zeile in der Frage kopiertfrom api import api_blueprint as api
— Kyle James Walker


4

Der current_appAnsatz ist in Ordnung, aber Sie müssen einen Anforderungskontext haben. Wenn Sie keine haben (z. B. Vorarbeiten wie Tests), sollten Sie diese besser platzieren

with app.test_request_context('/'):

vor diesem current_appAnruf.

Sie werden RuntimeError: working outside of application contextstattdessen haben.


3
Was ist, wenn die App in einer Fabrik erstellt wird und daher 'App' (oder wie auch immer man die Kolben-App nennt) nicht zum Importieren verfügbar ist? Innerhalb von Anfragen ist dies kein Problem, da bei Anfragen ein App-Kontext vorhanden ist, beim Definieren von Teilen außerhalb der Anforderungslogik jedoch eine App-Konfiguration erforderlich ist. Wie kann man auf die App-Konfiguration zugreifen, wenn Sie die App nicht zum Erstellen des Kontexts verwenden können?
— RobertoCuba


3

Sie müssen entweder die appHauptvariable (oder wie auch immer Sie sie genannt haben) importieren, die zurückgegeben wird von Flask():

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

Oder tun Sie dies innerhalb einer Anfrage:

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

4
Ja, ich wollte keines von beiden machen. Der erste ist das Erstellen von Querverweisen und der zweite Ansatz ist nicht trocken.
— Chirdeep Tomar

2
@ChirdeepTomar Wenn der erste Ansatz darin besteht, zirkuläre Importe zu erstellen (die die App beschädigen), stimmt etwas nicht mit der Struktur Ihrer App.
— Daniel Chatfield

13
@ DanielChatfield das ist einfach nicht wahr. Das App-Objekt ist das Objekt, das Blaupausen registriert. Wenn Sie vorschlagen, dass der Entwurf dann korrekt ist, um das App-Objekt zu importieren, entsteht immer eine zirkuläre Abhängigkeit. Weitere Antworten finden Sie in den richtigen Antworten.
— Sholsapp

@sholsapp Ich weiß, dass ein zirkulärer Import erstellt wird (genau wie in den Flask- Dokumenten: flask.pocoo.org/docs/patterns/packages ). Ich sagte, wenn ein zirkulärer Import erstellt wurde , der die App beschädigte .
— Daniel Chatfield

1

Sie können den Entwurf auch in eine Funktion einschließen und das appals Argument übergeben:

Entwurf:

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

Main:

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

Ich habe es versucht, aber ich habe einen "internen Serverfehler" erhalten.
— MD004

Irgendwelche Nachteile bei diesem Ansatz?
— Tuukka Mustonen

@ Tuukka: Ich erinnere mich an keine besonderen Nachteile, es ist ein bisschen zu lange her, seit ich es benutzt habe. Die flask.current_appVerwendung des Entwurfs in mehreren Apps bietet möglicherweise einige Vorteile . Ich würde vorschlagen, wenn dieser Ansatz Ihre Probleme löst, um ihn zu verwenden, erzwingt Flask keinen bestimmten Ansatz.
— Georg Schölly
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.