Làm cách nào để truy cập app.config trong bản thiết kế?


114

Tôi đang cố gắng truy cập cấu hình ứng dụng truy cập bên trong bản thiết kế authorisation.pytrong một gói api. Tôi đang khởi tạo bản thiết kế __init__.pyđược sử dụng trong đó 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)

Tôi nhận được RuntimeError: hoạt động bên ngoài ngữ cảnh ứng dụng

Tôi hiểu tại sao lại như vậy nhưng cách chính xác để truy cập các cài đặt cấu hình đó là gì?

---- Cập nhật ---- Tạm thời, tôi đã làm xong việc này.

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

Câu trả lời:


133

Sử dụng flask.current_appthay thế apptrong chế độ xem bản thiết kế.

from flask import current_app

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

Các current_appproxy là chỉ có sẵn trong bối cảnh của một yêu cầu .


25
Lưu ý rằng current_appproxy chỉ khả dụng trong ngữ cảnh của một yêu cầu.
sepehr

1
@sephr Bất kỳ mẹo nào về cách truy cập ngữ cảnh yêu cầu đó từ những nơi khác (mà không chuyển nó dưới dạng tham số mà là một số loại tham số toàn cục)?
carkod

21

recordPhương pháp nạp chồng có vẻ khá dễ dàng:

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
Đối với Python 3 sử dụng: app.config.items () thay vì app.config.iteritems ()
DhoTjai

1
Xin chào, tôi có cần gọi hoặc đăng ký record_params không, tôi đã thử nhưng không được. Cảm ơn rất nhiều.
MrBlue

Nếu bạn cần quyền truy cập vào một ứng dụng (ví dụ: lấy cấu hình để THIẾT LẬP bản thiết kế) thì điều này thật tuyệt!
Peter Lada

12

Để xây dựng câu trả lời của tbicr , đây là một ví dụ ghi đè ví dụ registerphương pháp :

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

Và một ví dụ sử dụng trình recordtrang trí :

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' không hoạt động với tôi ,. 'Api' từ không gian tên nào?
Tim Richardson

Xin lỗi đã không sao chép điều đó từ dòng trong câu hỏifrom api import api_blueprint as api
Kyle James Walker


4

Cách current_apptiếp cận là tốt nhưng bạn phải có một số ngữ cảnh yêu cầu. Nếu bạn không có (một số công việc trước như thử nghiệm, chẳng hạn), bạn nên đặt

with app.test_request_context('/'):

trước current_appcuộc gọi này .

Bạn sẽ có RuntimeError: working outside of application context, thay vào đó.


3
Còn khi ứng dụng được tạo trong nhà máy và do đó 'ứng dụng' (hoặc bất cứ thứ gì người ta gọi là ứng dụng bình) không có sẵn để nhập? Các yêu cầu bên trong không có vấn đề gì vì trong các yêu cầu có ngữ cảnh ứng dụng, nhưng khi xác định các phần bên ngoài logic yêu cầu yêu cầu cấu hình ứng dụng. làm thế nào để một người có thể truy cập cấu hình ứng dụng nếu bạn không thể sử dụng ứng dụng để tạo ngữ cảnh?
RobertoCuba


3

Bạn cần nhập appbiến chính (hoặc bất kỳ biến nào bạn đã gọi) được trả về bởi Flask():

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

Hoặc làm điều đó từ trong một yêu cầu:

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

4
Phải, tôi không muốn làm cả hai. Đầu tiên là tạo các tham chiếu chéo và cách tiếp cận thứ hai là không KHÔ.
Chirdeep Tomar

2
@ChirdeepTomar Nếu cách tiếp cận đầu tiên là tạo nhập vòng tròn (phá vỡ ứng dụng) thì có điều gì đó không ổn với cách ứng dụng của bạn được cấu trúc.
Daniel Chatfield

13
@DanielChatfield điều đó đơn giản là không đúng. Đối tượng ứng dụng là đối tượng đăng ký bản thiết kế. Đề xuất rằng nó đúng cho bản thiết kế sau đó nhập đối tượng ứng dụng sẽ luôn gây ra sự phụ thuộc vòng tròn. Xem các câu trả lời khác để biết chiến lược chính xác.
sholsapp

@sholsapp Tôi biết nó sẽ tạo một phép nhập vòng tròn (giống như cách làm trong tài liệu flask: flask.pocoo.org/docs/patterns/packages ), tôi đã nói nếu nó tạo một phép nhập vòng tròn đã phá vỡ ứng dụng .
Daniel Chatfield,

1

Bạn cũng có thể bao bọc bản thiết kế trong một hàm và chuyển applàm đối số:

Bản vẽ thiết kế:

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

Chủ yếu:

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

Tôi đã thử điều này nhưng gặp phải "Lỗi máy chủ nội bộ".
MD004

Bất kỳ hạn chế với cách tiếp cận này?
Tuukka Mustonen

@Tuukka: Tôi không nhớ bất kỳ nhược điểm cụ thể nào, đã quá lâu rồi tôi không sử dụng nó. Có thể có một số lợi ích flask.current_appkhi bạn sử dụng bản thiết kế trong nhiều ứng dụng. Tôi sẽ đề xuất nếu phương pháp này giải quyết được các vấn đề của bạn để sử dụng nó, Flask không thực thi một phương pháp cụ thể.
Georg Schölly
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.