2016-01-30 218 views
3

我是Flask的新手,我即將編寫一個更大的應用程序。到目前爲止,我已將功能劃分爲藍圖。現在我希望能夠在初始化期間從藍圖內設置一些全局變量(因此在請求上下文之外)。基本上,我想自動初始化某些藍圖的導航列表,因此每個藍圖都需要告訴我的基本應用程序如何命名以及默認路線是什麼。Flask藍圖初始化 - 初始化一些全局變量

我的目標是讓其他人可以通過將他們的自定義藍圖放入我的應用程序的「插件」文件夾來擴展我的應用程序。在這種情況下,我的應用程序不知道他們的路線或名稱。它需要自動學習它,同時加載特定的藍圖...

要解釋它以某種其他方式:我有一個主要應用程序包含一些子應用程序實現爲藍圖。主應用程序應該包含一個引用所有子應用程序(藍圖)的導航欄。藍圖如何在主菜單導航變量上註冊一些東西(例如初始化時)?

(我沒有找到一種方法來訪問類似「self.parent」或從藍圖應用程序上下文,不要藍圖碰到這樣一個構造函數?)

回答

0

所以每個藍圖的需求告訴我的基礎應用程序如何命名 以及它的默認路由是什麼。

當你創建一個藍圖,你已經在第一個參數傳遞它的名字:

simple_page = Blueprint('simple_page') 

可以傳遞給構造url_prefix值太大

simple_page = Blueprint('simple_page', url_prefix='/pages') 

我有一個主要應用程序,其中包含一些子應用程序 作爲藍圖。主要應用應該持有一個導航欄 引用到所有的子應用程序(藍圖)

這是一個Python模塊的例子,你應該拆了自己的模塊中的每個藍圖。

from flask import Flask, Blueprint, render_template 

# ADMIN 
admin = Blueprint('admin', __name__, url_prefix='/admin') 

@admin.route('/') 
def admin_index(): 
    return 'Admin module' 

@admin.route('/settings') 
def settings(): 
    return 'Admin Settings' 


# USER 
user = Blueprint('user', __name__, url_prefix='/user') 

@user.route('/') 
def user_index(): 
    return 'User module' 

@user.route('/profile') 
def profile(): 
    return 'User Profile' 


app = Flask(__name__) 
app.register_blueprint(admin) 
app.register_blueprint(user) 

@app.route('/') 
def index(): 
    return render_template('index.html', blueprints=app.blueprints) 

if __name__ == '__main__': 
    app.run(host='0.0.0.0', debug=True, port=7000) 

Jinja2模板。請記住將此文件放置在您的根項目的模板文件夾中,默認情況下,該文件夾將在其中進行模板搜索。

<ul> 
    {% for bp_name, bp in blueprints.iteritems() %} 
    <li><a href="{{ bp.url_prefix }}">{{ bp.name }}</a></li> 
    {% endfor %} 
</ul> 

從燒瓶中主要應用對象,在這種情況下應用,您可以訪問註冊藍圖的列表; app.blueprints,這是一個python字典,其中包含您在構造函數中傳遞的藍圖的名稱。所以你將這個對象傳遞給你模板並循環它以在菜單中呈現名稱和URL。

而且,如果我想要的東西,使藍圖作者能夠以標準化的方式傳遞更多 數據(例如,在色彩顯示的鏈接 他的作品,或任何...)

由於這是一個藍圖的具體數據,我認爲一個好的解決辦法是延長藍圖類,並實現自定義的方法來保存在一個標準化的方式額外的數據,然後從主要應用對象訪問即可。

custom.py

from flask import Blueprint 

class MyBlueprint(Blueprint): 

    bp_data = {} 

    def set_data(data): 
     # here you can make extra task like ensuring if 
     # a minum group of value were provided for instance 
     bp_data = data 

admin.py

from .custom import MyBlueprint 

admin = MyBlueprint('admin', __name__, url_prefix='/admin') 
admin.set_data({'color': '#a569bd', 'enabled': true}) 

# all the blueprint's routes 
... 

app.py

from admin import admin 

app = Flask(__name__) 
app.register_blueprint(admin) 

@app.route('/') 
def index(): 
    for a, b in app.blueprints: 
     print b.bp_data['color'] 
     print b.bp_data['enabled'] 
    ... 

當然,我的自定義藍圖類需要它更多的工作,比如驗證什麼如果沒有所需的值,則傳遞的數據類型或拋出錯誤,如; title,require_auth等。從這一點出發,您必須定義藍圖必須提供給主應用程序才能正常工作所需的最小數據量。

+0

謝謝你的回答。確實如此,但是這種情況發生在藍圖內,並且由編寫藍圖並將其添加到我的基本應用程序的人員來定義。但是,我現在應該如何收集所有藍圖主路線和名稱,以便在應用程序上下文中生成導航(例如,將其保存在應用程序上下文中以便稍後在調用URL時使用它)? 此外,如果我想讓藍圖作者以標準方式傳遞更多數據(例如用哪種顏色來顯示鏈接到他的作品,或者其他什麼),該怎麼辦。 –

+0

在主應用程序實例中,您有藍圖字典,您可以循環以獲取藍圖的每個實例並訪問其屬性。我會更新我的答案。 – miso

+0

謝謝,這解決了我的問題的核心。不過,我真的很想將藍圖中的更多設置/數據傳遞到應用程序上下文...以進一步自定義。 假設一個藍圖需要告訴它的優先級(它應該放置鏈接的位置),還是一個顏色,或者是否要禁止它被列出來...... –

0

這裏我介紹一個我通常使用的可擴展應用程序模式。事實證明,工作很好。

目錄結構:

YourApp 
|- plugins (will contain all the user's plugins) 
    |- __init__.py (empty) 
    |-plugin1 
      |- __init__.py (empty) 
      |- loader.py 
|- app.py 

app.py

from flask import Flask 
import os 

def plugin_loader(app): 
    """ Function for discover new potencial plugins. 
    After checking the validity (it means, check if it implements 
    'register_as_plugin', load the user defined blueprint""" 

    plugins = [x for x in os.listdir('./plugins') 
      if os.path.isdir('./plugins/' + x)] 
    for plugin in plugins: 
    # TODO: Add checking for validation 
    module = __import__('plugins.' + str(plugin) + '.loader', fromlist=['register_as_plugin']) 

    app = module.register_as_plugin(app) 

    return app 

# Creates the flask app 
app = Flask(__name__) 
# Load the plugins as blueprints 
app = plugin_loader(app) 

print(app.url_map) 


@app.route('/') 
def root(): 
    return "Web root!" 

app.run() 

插件/ plugin1/loader.py

from flask import Blueprint 


plugin1 = Blueprint('plugin1', __name__) 

@plugin1.route('/version') 
def version(): 
    return "Plugin 1" 

def register_as_plugin(app): 
    app.register_blueprint(plugin1, url_prefix='/plugin1') 

    return app 

所以期貨插件應該實現register_as_plugin函數在loader.py文件中,在plugins /目錄下的目錄中。

有關目錄發現的更多信息,您可以閱讀https://docs.python.org/2/library/os.path.html。 有關動態導入模塊的更多信息,請參閱https://docs.python.org/2/library/functions.html#import

用Python 2.7.6,Flask 0.10.1和Unix平臺驗證。