Bir plandaki app.config'e nasıl erişilir?


115

authorisation.pyBir paket api'sinde bulunan bir plan içindeki erişim uygulaması yapılandırmasına erişmeye çalışıyorum . İçinde __init__.pykullanılan planı başlatıyorum 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 alıyorum: uygulama bağlamının dışında çalışıyor

Bunun neden olduğunu anlıyorum ama o zaman bu yapılandırma ayarlarına erişmenin doğru yolu nedir?

---- Güncelle ---- Geçici olarak, bunu yaptım.

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

Yanıtlar:


133

Plan görünümünde flask.current_appyerine kullanın app.

from flask import current_app

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

current_appVekil bir bağlamında yalnızca istek .


25
current_appProxy'nin yalnızca bir istek bağlamında kullanılabildiğini unutmayın .
sepehr

1
@sephr Bu istek bağlamına başka yerlerden nasıl erişileceğine dair herhangi bir ipucu (bunu bir parametre olarak iletmeden, ancak bir tür genel parametre olarak)?
carkod

21

Aşırı yükleme recordyöntemi oldukça kolay görünüyor:

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 için şunu kullanın: app.config.iteritems () yerine app.config.items ()
DhoTjai

1
Merhaba, record_params'ı çağırmam veya kaydetmem gerekiyor mu, denedim ama işe yaramadı. Çok teşekkürler.
mrblue

Bir uygulamaya erişmeniz gerekiyorsa (örneğin planı AYARLAMAK için yapılandırmayı almak) bu harika!
Peter Lada

12

Tbicr'in cevabının üzerine inşa etmek için , işte registeryöntem örneğini geçersiz kılan bir örnek:

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

Ve recorddekoratörün kullanıldığı bir örnek :

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' benim için çalışmıyor. 'Api' hangi ad alanına ait?
Tim Richardson

Maalesef sorudaki satırdan bunu kopyalamadımfrom api import api_blueprint as api
Kyle James Walker


4

current_appYaklaşım iyi ama bazı istek bağlamı olması gerekir. Eğer bir hesabınız yoksa (örneğin test gibi bazı ön çalışmalar)

with app.test_request_context('/'):

bu current_apparamadan önce .

Onun RuntimeError: working outside of application contextyerine alacaksın.


3
Uygulama bir fabrikada oluşturulduğunda ve bu nedenle 'uygulama' (veya flask uygulaması olarak adlandırılan her şey) içe aktarılamaz olduğunda ne olacak? İç istekler sorun değildir, çünkü istekler sırasında bir uygulama bağlamı vardır, ancak uygulama yapılandırması gerektiren istek mantığının dışındaki parçaları tanımlarken. Bağlamı oluşturmak için uygulamayı kullanamıyorsanız uygulama yapılandırmasına nasıl erişebilirsiniz?
RobertoCuba


3

Ya appşu şekilde döndürülen ana değişkeni (ya da ne adlandırdığınızı) içe aktarmanız gerekir Flask():

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

Veya bunu bir istek içinde yapın:

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

4
Evet, ikisini de yapmak istemedim. Birincisi çapraz referanslar oluşturmaktır ve ikinci yaklaşım KURU değildir.
Chirdeep Tomar

2
@ChirdeepTomar İlk yaklaşım döngüsel içe aktarmalar oluşturmaksa (uygulamayı bozan), o zaman uygulamanızın nasıl yapılandırıldığıyla ilgili yanlış bir şeyler vardır.
Daniel Chatfield

13
@DanielChatfield bu kesinlikle doğru değil. Uygulama nesnesi, planları kaydeden nesnedir. Plan için doğru olduğunu ve ardından uygulama nesnesini içe aktarmak her zaman döngüsel bir bağımlılığa neden olur. Doğru strateji için diğer yanıtlara bakın.
sholsapp

@sholsapp Dairesel bir içe aktarma oluşturacağını biliyorum (tıpkı flask belgelerinde olduğu gibi: flask.pocoo.org/docs/patterns/packages ), uygulamayı bozan döngüsel bir içe aktarma oluşturup oluşturmadığını söyledim .
Daniel Chatfield

1

Ayrıca planı bir fonksiyona sarabilir ve appargüman olarak iletebilirsiniz :

Taslak:

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

Ana:

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

Bunu denedim ama "Dahili Sunucu Hatası" aldım.
MD004

Bu yaklaşımın herhangi bir sakıncası var mı?
Tuukka Mustonen

@Tuukka: Herhangi bir dezavantajı hatırlamıyorum, kullanmayalı biraz uzun zaman oldu. flask.current_appPlanı birden fazla uygulamada kullandığınızda kullanmanın bazı avantajları olabilir . Bu yaklaşım sorunlarınızı çözerse, Flask'ın belirli bir yaklaşımı uygulamadığını öneririm.
Georg Schölly
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.