Bagaimana cara mengakses app.config di cetak biru?


114

Saya mencoba mengakses konfigurasi aplikasi akses di dalam cetak biru authorisation.pyyang dalam api paket. Saya menginisialisasi cetak biru __init__.pyyang digunakan dalam 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)

Saya mendapatkan RuntimeError: bekerja di luar konteks aplikasi

Saya mengerti mengapa demikian, tetapi kemudian bagaimana cara yang benar untuk mengakses pengaturan konfigurasi tersebut?

---- Perbarui ---- Untuk sementara, saya telah melakukan ini.

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

Jawaban:


133

Gunakan flask.current_appsebagai pengganti appdalam tampilan cetak biru.

from flask import current_app

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

The current_appproxy hanya tersedia dalam konteks permintaan .


25
Perhatikan bahwa current_appproxy hanya tersedia dalam konteks permintaan.
Sepehr

1
@sephr Ada tips tentang cara mengakses konteks permintaan itu dari tempat lain (tanpa meneruskannya sebagai parameter, tetapi sebagai semacam parameter global)?
carkod

21

recordMetode overloading sepertinya cukup mudah:

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
Untuk Python 3, gunakan: app.config.items () daripada app.config.iteritems ()
DhoTjai

1
Hai, apakah saya perlu memanggil atau mendaftar record_params, saya sudah mencoba tetapi tidak berhasil. Terima kasih banyak.
mrblue

Jika Anda memerlukan akses ke suatu aplikasi (misalnya mendapatkan konfigurasi untuk MENGATUR cetak biru) ini bagus!
Peter Lada

12

Untuk membangun jawaban tbicr , berikut adalah contoh yang menggantikan contoh registermetode :

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

Dan contoh menggunakan recorddekorator :

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' tidak bekerja untuk saya,. Dari namespace apa 'api' itu?
Tim Richards

Maaf tidak menyalin itu dari baris dalam pertanyaanfrom api import api_blueprint as api
Kyle James Walker


4

The current_apppendekatan baik-baik saja tetapi Anda harus memiliki beberapa konteks permintaan. Jika Anda tidak memilikinya (beberapa pekerjaan awal seperti pengujian, misalnya) sebaiknya Anda menempatkannya

with app.test_request_context('/'):

sebelum current_apppanggilan ini .

Anda akan memiliki RuntimeError: working outside of application context, sebagai gantinya.


3
Bagaimana dengan saat aplikasi dibuat di pabrik dan oleh karena itu 'app' (atau apa pun yang disebut aplikasi flask) tidak tersedia untuk diimpor? Permintaan di dalam tidak masalah karena selama permintaan ada konteks aplikasi, tetapi ketika mendefinisikan bagian di luar logika permintaan yang memerlukan konfigurasi aplikasi. bagaimana seseorang bisa mengakses konfigurasi aplikasi jika Anda tidak dapat menggunakan aplikasi untuk membuat konteks?
RobertoCuba


3

Anda juga perlu mengimpor appvariabel utama (atau apa pun yang Anda sebut itu) yang dikembalikan oleh Flask():

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

Atau lakukan itu dari dalam permintaan:

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

4
Ya, saya tidak ingin melakukan salah satu dari keduanya. Pertama membuat referensi silang dan pendekatan kedua tidak KERING.
Chirdeep Tomar

2
@ChirdeepTomar Jika pendekatan pertama adalah membuat impor melingkar (yang merusak aplikasi), maka ada yang salah dengan struktur aplikasi Anda.
Daniel Chatfield

13
@DanielChatfield itu tidak benar. Objek aplikasi adalah objek yang mendaftarkan cetak biru. Menyarankan bahwa itu benar untuk cetak biru kemudian mengimpor objek aplikasi akan selalu menyebabkan ketergantungan melingkar. Lihat jawaban lain untuk strategi yang benar.
sholsapp

@sholsapp Saya tahu ini akan membuat impor melingkar (seperti yang terjadi di flask docs: flask.pocoo.org/docs/patterns/packages ), saya katakan jika itu membuat impor melingkar yang merusak aplikasi .
Daniel Chatfield

1

Anda juga bisa membungkus cetak biru dalam sebuah fungsi dan meneruskan appsebagai argumen:

Cetak biru:

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

Utama:

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

Saya mencoba ini, tetapi saya mendapat "Kesalahan Server Internal".
MD004

Adakah kelemahan dengan pendekatan ini?
Tuukka Mustonen

@Tuukka: Saya tidak ingat kekurangan tertentu, sudah terlalu lama sejak saya menggunakannya. Mungkin ada beberapa keuntungan menggunakan flask.current_appsaat Anda menggunakan cetak biru di beberapa aplikasi. Saya akan menyarankan jika pendekatan ini menyelesaikan masalah Anda untuk menggunakannya, Flask tidak menerapkan pendekatan khusus.
Georg Schölly
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.