วิธีเข้าถึง app.config ในพิมพ์เขียว?


116

ฉันกำลังพยายามเข้าถึงการกำหนดค่าแอปพลิเคชันภายในพิมพ์เขียวauthorisation.pyซึ่งอยู่ในแพ็คเกจ API ฉันกำลังเริ่มต้นพิมพ์เขียว__init__.pyที่ใช้ใน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: กำลังทำงานนอกบริบทของแอปพลิเคชัน

ฉันเข้าใจว่าเหตุใดจึงเป็นเช่นนั้น แต่วิธีใดที่ถูกต้องในการเข้าถึงการตั้งค่าการกำหนดค่าเหล่านั้น

---- อัปเดต ---- ฉันได้ดำเนินการนี้ชั่วคราวแล้ว

@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พร็อกซีจะพร้อมใช้งานในบริบทของคำขอเท่านั้น
59

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

หากคุณต้องการเข้าถึงแอป (เช่นรับการกำหนดค่าสำหรับการตั้งค่าพิมพ์เขียว) สิ่งนี้ยอดเยี่ยมมาก!
Peter Lada

13

เพื่อสร้างคำตอบของ 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' มาจากอะไร?
Tim Richardson

ขออภัยไม่ได้คัดลอกจากบรรทัดในคำถามfrom api import api_blueprint as api
Kyle James Walker


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 หากแนวทางแรกคือการสร้างการนำเข้าแบบวงกลม (ซึ่งทำให้แอปหยุดทำงาน) แสดงว่ามีบางอย่างผิดปกติกับโครงสร้างแอปของคุณ
Daniel Chatfield

13
@DanielChatfield นั่นไม่เป็นความจริง วัตถุแอปคือวัตถุที่ลงทะเบียนพิมพ์เขียว บอกว่ามันเป็นที่ถูกต้องสำหรับพิมพ์เขียวแล้วที่จะนำเข้าวัตถุ app ที่จะเสมอทำให้เกิดการพึ่งพาวงกลม ดูคำตอบอื่น ๆ สำหรับกลยุทธ์ที่ถูกต้อง
sholsapp

@sholsapp ฉันรู้ว่ามันจะสร้างการนำเข้าแบบวงกลม (เช่นเดียวกับที่ทำในเอกสารขวด: flask.pocoo.org/docs/patterns/packages ) ฉันบอกว่ามันสร้างการนำเข้าแบบวงกลมที่ทำให้แอปเสียหายหรือไม่
Daniel Chatfield

1

คุณยังสามารถรวมพิมพ์เขียวในฟังก์ชันและส่งappเป็นอาร์กิวเมนต์:

พิมพ์เขียว:

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

หลัก:

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

ฉันลองแล้ว แต่ได้รับ "ข้อผิดพลาดภายในเซิร์ฟเวอร์"
MD004

ข้อเสียใด ๆ กับแนวทางนี้?
Tuukka Mustonen

@Tuukka: ฉันจำข้อบกพร่องใด ๆ ไม่ได้เลยมันนานเกินไปแล้วที่ฉันใช้มัน อาจมีข้อดีบางประการflask.current_appเมื่อคุณใช้พิมพ์เขียวในหลายแอพ ฉันขอแนะนำว่าหากวิธีนี้ช่วยแก้ปัญหาของคุณเพื่อใช้งานได้ Flask ไม่ได้บังคับใช้แนวทางเฉพาะ
Georg Schölly
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.