使用app dispatch技術將多個Flask應用組合成一個

動機

最近我們機器人後臺系統承接的業務越來越多,除了機器人本身的後臺,還有門禁系統、廣告系統等的後臺,都需要單獨的登錄流程(門禁還細分PC端小區物業登錄和app端業主登錄),但是我發現flask-login跟Flask app是一一對應關係,即一個app內只可能存在一個login manager,所以爲了運行多個login manager,只能運行多個app

app dispatch技術

Application Dispatching是WSGI工具箱werkzeug提供的一種技術,目的是將多個Flask應用按URL前綴組合成一個應用

class DispatcherMiddleware(__builtin__.object)
 |  Allows one to mount middlewares or applications in a WSGI application.
 |  This is useful if you want to combine multiple WSGI applications::
 |  
 |      app = DispatcherMiddleware(app, {
 |          '/app2':        app2,
 |          '/app3':        app3
 |      })

實現

官方文檔的示例不完整,而且就兩級嵌套,不符合我們3級業務的需求(機器人登錄/門禁登錄/門禁管理員登錄),所以決定自己實現一下

目錄結構

nest
├── test_app_dispatch.py
├── ad
│   └── __init__.py
└── yeelink
    ├── __init__.py
    └── admin
        └── __init__.py

每一層組合,或者說嵌套,其模式是一模一樣的,類似遞歸/分形,所以我只把nest跟yeelink/ad的組合代碼貼出來
nest/test_app_dispatch.py內容

#encoding = utf-8

from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.serving import run_simple
from flask import Flask
from yeelink import app as app_yeelink
from ad import app as app_ad

app = Flask(__name__)
app.secret_key = 'topLevel'

@app.route('/')
def index():
    return 'Hello top level!'

app = DispatcherMiddleware(app,{
    '/yeelink':     app_yeelink,
    '/ad':     app_ad
})

if __name__ == '__main__':
    run_simple('localhost', 5000, app,
               use_reloader=True, use_debugger=True, use_evalex=True)

nest/yeelink/__init__.py

#encoding = utf-8

from werkzeug.wsgi import DispatcherMiddleware
from flask import Flask,current_app,request,redirect,session,flash,url_for
from admin import app as app_admin

app = Flask(__name__)
app.secret_key = 'yeelink'

@app.route('/')
def index():
    return 'yeelink Page'

app = DispatcherMiddleware(app,{
    '/admin':     app_admin
})  

注意

DispatcherMiddleware實例不是Flask實例,沒有route裝飾器,所以該類的調用一定要放到所有@app.route語句的後面,否則會報以下錯誤:

Traceback (most recent call last):
  File "test_app_dispatch.py", line 17, in <module>
    @app.route('/')
AttributeError: 'DispatcherMiddleware' object has no attribute 'route'

因爲頂層wsgi對象在import所有模塊時,是按順序執行模塊語句的,所以當import執行到app.route時,app綁定的仍是Flask實例,但是執行DispatcherMiddleware後,app綁定的已經是DispatcherMiddleware實例了,最終由run_simple()方法運行該組合後的實例。

總結

app dispatch技術實現了app的隔離(獨立的login managersecret_key等),同時讓每層業務系統都能模塊化(只關心自己的URL部分),很有用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章