Come accedere ad app.config in un progetto?


114

Sto cercando di accedere alla configurazione dell'applicazione di accesso all'interno di un progetto authorisation.pyche in un pacchetto api. Sto inizializzando il progetto in __init__.pycui viene utilizzato in 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)

Ricevo RuntimeError: lavoro al di fuori del contesto dell'applicazione

Capisco il motivo, ma qual è il modo corretto di accedere a tali impostazioni di configurazione?

---- Aggiorna ---- Temporaneamente, l'ho fatto.

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

Risposte:


133

Utilizzare flask.current_appal posto di appnella visualizzazione del progetto.

from flask import current_app

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

Il current_appproxy è disponibile solo nel contesto di una richiesta .


25
Notare che il current_appproxy è disponibile solo nel contesto di una richiesta.
sepehr

1
@sephr Qualche suggerimento su come accedere a quel contesto di richiesta da altri posti (senza passarlo come parametro, ma come una sorta di parametro globale)?
carkod

21

Il recordmetodo di sovraccarico sembra essere abbastanza semplice:

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
Per Python 3 usa: app.config.items () invece di app.config.iteritems ()
DhoTjai

1
Ciao, devo richiamare o registrare record_params, ho provato ma non ha funzionato. Molte grazie.
mrblue

Se hai bisogno di accedere a un'app (ad esempio ottenere la configurazione per IMPOSTAZIONE del progetto) è fantastico!
Peter Lada

12

Per basarsi sulla risposta di tbicr , ecco un esempio che sovrascrive l' esempio del registermetodo :

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

E un esempio usando il recorddecoratore :

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" non funziona per me,. Da quale spazio dei nomi proviene "api"?
Tim Richardson,

Mi dispiace non averlo copiato dalla riga nella domandafrom api import api_blueprint as api
Kyle James Walker,


4

L' current_appapproccio va bene ma devi avere un contesto di richiesta. Se non ne hai uno (alcuni pre-lavoro come il test, ad esempio) è meglio che tu lo faccia

with app.test_request_context('/'):

prima di questa current_appchiamata.

Avrai RuntimeError: working outside of application context, invece.


3
E quando l'app viene creata in una fabbrica e quindi "app" (o qualunque cosa si chiami l'app flask) non è disponibile per essere importata? All'interno delle richieste non è un problema perché durante le richieste c'è un contesto dell'app, ma quando si definiscono parti al di fuori della logica di richiesta che richiedono la configurazione dell'app. come si può accedere alla configurazione dell'app se non è possibile utilizzare l'app per creare il contesto?
RobertoCuba


3

È necessario importare la appvariabile principale (o qualunque cosa tu abbia chiamato) che viene restituita da Flask():

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

Oppure fallo dall'interno di una richiesta:

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

4
Sì, non volevo fare nessuno dei due. Il primo è creare riferimenti incrociati e il secondo approccio non è DRY.
Chirdeep Tomar

2
@ChirdeepTomar Se il primo approccio è la creazione di importazioni circolari (che interrompono l'app), allora c'è qualcosa che non va nel modo in cui è strutturata la tua app.
Daniel Chatfield

13
@DanielChatfield semplicemente non è vero. L'oggetto app è l'oggetto che registra i progetti. Suggerire che sia corretto per il progetto quindi importare l'oggetto app causerà sempre una dipendenza circolare. Vedi altre risposte per la strategia corretta.
sholsapp

@sholsapp So che creerà un'importazione circolare (proprio come fa nella documentazione del flask: flask.pocoo.org/docs/patterns/packages ), ho detto se ha creato un'importazione circolare che ha rotto l'app .
Daniel Chatfield

1

Puoi anche racchiudere il progetto in una funzione e passare appcome argomento:

Planimetria:

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

Principale:

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

Ho provato questo, ma ho ricevuto un "Errore interno del server".
MD004

Qualche inconveniente con questo approccio?
Tuukka Mustonen,

@Tuukka: non ricordo alcun inconveniente particolare, è passato troppo tempo da quando l'ho usato. Potrebbero esserci alcuni vantaggi nell'usare flask.current_appil progetto in più app. Suggerirei se questo approccio risolve i tuoi problemi di usarlo, Flask non applica un approccio specifico.
Georg Schölly,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.