標籤:

第一期 · 如何理解Flask中的藍圖?

正常情況下,入門Flask框架都是從寫一個單文件,然後看到頁面顯示 Hello,World! 開始的。這個單文件一般命名hello.py或run.py。

你會在單文件中寫一些路由,比如首頁的、列表頁的、詳情頁的,就像我博客這麼簡單的頁面結構,完全可以一個文件搞定。

# -*- coding: utf-8 -*-n # run.pyn from flask import Flask, render_template, requestn from flask_flatpages import FlatPagesnn FLATPAGES_AUTO_RELOAD = Truen FLATPAGES_ROOT = pagesn FLATPAGES_EXTENSION = .mdnnn app = Flask(__name__)n app.config.from_object(__name__)n flatpages = FlatPages(app)nn # 首頁n @app.route(/)n def index():n passnn # 文章列表n @app.route(/list/<string:tag>/)n def page_list(tag):n passnn # 文章詳情n @app.route(/page/<string:uri>/)n def page(uri):n passnn if __name__ == __main__:n app.run() n

上面是一個可以運行的微型博客的全部後端程序,幾乎就是你現在正常訪問的博客的全部,你看,非常簡短!

如果你用過類似WordPress或者新浪博客等博客工具,顯然有一個問題:哪兒可以添加新的文章和管理文章分類?的確,這段代碼離一個傳統的博客程序該有的全貌相差甚遠,因為還欠缺一個管理後台。

以WordPress為例子,在一般情況下,如果訪問如xxx.com,可以看到博客的前台,也就是各種博客文章。而訪問如xxx.com/wp-admin 則可以進入到後台,用來管理文章和發布新文章。在路由的寫法上,對於上面這個文件你可能要這樣擴充一下功能(為了節省篇幅方便演示,下面代碼詳細部分省略,以 pass 代替詳細部分)。

# -*- coding: utf-8 -*-n # run.pyn from flask import Flask, render_template, requestn from flask_flatpages import FlatPagesnn FLATPAGES_AUTO_RELOAD = Truen FLATPAGES_ROOT = pagesn FLATPAGES_EXTENSION = .mdnnn app = Flask(__name__)n app.config.from_object(__name__)n flatpages = FlatPages(app)nn @app.route(/)n def index():n pass # 為了方便演示這裡省略詳細代碼nn @app.route(/list/<string:tag>/)n def page_list(tag):n passnn @app.route(/page/<string:uri>/)n def page(uri):n pass nn # 新增的後台部分代碼n @app.route(/admin/login/)n def admin_login():n pass nn @app.route(/admin/page/)n def admin_pages():n pass nn @app.route(/admin/page/new/)n def new_page():n pass nn @app.route(/admin/page/edit/)n def edit_page():n pass nn if __name__ == __main__:n app.run() n

上述代碼新增加了管理後台部分,具體是增加了一個後台登錄界面、文章列表以及新增和編輯文章的功能共四個部分。

繼續上述思路,可以想到新的幾個問題:

1)一般情況下,前台和後台用兩套模板。或者通俗的講,前台費力弄得好看點,後台反正自己用,能用就成,丑點無所謂。那麼怎麼讓前台和後台用兩套模板?

2)後台部分邏輯比前台複雜,還需要導入新的包,如果和前台寫在一個文件里,後面修改會不會容易出錯,例如本來改後台部分結果牽連前台出問題?

3)既然Python力求簡潔,那代碼能否再簡潔些?比如新增的路由參數 /admin 重複寫了4遍,能不能對後台定義一個前綴,後台部分的自動加這個/admin ?

4)如果這個博客程序需要多人來維護,多人編輯同一個文件去提交時衝突如何解決?

亦或者你還有其他的一些疑問,如果是關乎怎麼把程序做大的同時,還能保證簡潔、良好、易於維護的代碼組織結構,一個容易想到的方向就是程序的「模塊化」。

在你學習Python的過程中,早已見識到了Python模塊化,比如Python的包概念,也即你總是能看到的 import …… 引入的那些東西和本身的這個引入方法。那麼,對於Flask而言,你也許會舉一反三的把博客的後台程序部分抽離出來,單獨編寫一個文件,然後再 import …… ,這樣不就模塊化了?!

但是等等,程序跑不起來了?還有,前面剛提到過的四個問題,似乎這樣做之後只是勉強解決了第四個問題,前三個呢?

所以,可想而知,我們的確需要一個模塊化的方法,這個思路的方向本身不錯,要點在於我們需要的是一個Flask認可的、兼容的、支持的模塊化方法。Flask的作者作為一個老江湖早就考慮到這點,並提供了一個名為Blueprint的方法來讓你實現模塊化組織程序結構。

Blueprint中文的翻譯現在有兩種常見的:藍圖以及藍本。這裡我們稱藍圖好了。

對於上述程序,我們應用藍圖方法修改之後,大致是下面這樣了。

首先,我們新增一個文件adminPages.py,如下:

# -*- coding: utf-8 -*-n # adminPages.pyn from flask import Blueprintnnn admin = Blueprint(admin, __name__)nnn @admin.route(/login/)n def admin_login():n pass nn @admin.route(/page/)n def admin_pages():n pass nn @admin.route(/page/new/)n def new_page():n pass nn @admin.route(/page/edit/)n def edit_page():n pass n

同時,改寫run.py 如下:

# -*- coding: utf-8 -*-n # run.pyn from flask import Flask, render_template, requestn from flask_flatpages import FlatPagesnn FLATPAGES_AUTO_RELOAD = Truen FLATPAGES_ROOT = pagesn FLATPAGES_EXTENSION = .mdnnn app = Flask(__name__)n app.config.from_object(__name__)n flatpages = FlatPages(app)nn @app.route(/)n def index():n pass # 為了方便演示這裡省略詳細代碼nn @app.route(/list/<string:tag>/)n def page_list(tag):n passnn @app.route(/page/<string:uri>/)n def page(uri):n pass nn # 新增的後台部分代碼n from adminPages import adminn app.register_blueprint(admin, url_prefix=/admin) nn if __name__ == __main__:n app.run() n

好,這就完成了一個應用藍圖的簡單例子。讓我們再來回顧上述代碼,看看都做了些什麼。

首先,我們新增了一個adminPages.py的文件,並在文件中導入了Flask的藍圖方法Blueprint。

緊接著,我們用admin實例化了一個藍圖應用,就是這句:

admin = Blueprint(admin, __name__)n

Blueprint要求至少傳入兩個參數,分別是藍圖的名字和藍圖所在的包或模塊。

我們將後台部分獨立出來作為藍圖模塊,並取名為 admin ,所以我們傳入第一個參數admin。

緊接著是所在的包或模塊,如果你有印象,大概還記得Python有一個特殊屬性_ name _ ,當用在一個文件里時,代表的是模塊(或包)的名字,所以第二個參數傳入 _ name _ 。

因為使用了藍圖,原來的路由 @app.route() 改寫成了 @admin.route(),改寫的原因你需要看一下官方文檔了解更為深入的細節,這裡暫且不表。

對於run.py,我們剝離出了 admin 部分的程序代碼,但在文件末尾,又導入了藍圖模塊,然後按照Flask藍圖的用法去註冊了藍圖,就是這兩行代碼:

from adminPages import admin napp.register_blueprint(admin, url_prefix=/admin)n

其中,app.register_blueprint()的第一個參數無需過多解釋,第二個參數 url_prefix= 即在定義前綴。還記得前面的四個問題嗎?這裡針對的就是第三個問題。再回過頭去看看,你會發現adminPages.py里,原來路由里的 /admin 都去掉了。

就是這些,我們簡單的應用了一把Flask的藍圖功能,一定程度上算是解決了前面四個問題中的三個,還有一個兩套模板的問題藍圖也支持,並且十分簡單,留給你去看看官方文檔了解吧。

提示:template_folder=


推薦閱讀:

Flask文件上傳(四):文件管理與多文件上傳
Flask文件上傳系列目錄索引
flask 角色驗證中位操作求解?
Flask表單:自定義表單樣式

TAG:Python | Flask |