buleprint

来源:互联网 发布:www.js study.com 编辑:程序博客网 时间:2024/05/05 22:15

第一期 · 如何理解Flask中的蓝图?


正常情况下,入门Flask框架都是从写一个单文件,然后看到页面显示 Hello,World! 开始的。这个单文件一般命名hello.py或run.py。

你会在单文件中写一些路由,比如首页的、列表页的、详情页的,就像我博客这么简单的页面结构,完全可以一个文件搞定。

    # -*- coding: utf-8 -*-    # run.py    from flask import Flask, render_template, request    from flask_flatpages import FlatPages    FLATPAGES_AUTO_RELOAD = True    FLATPAGES_ROOT = 'pages'    FLATPAGES_EXTENSION = '.md'    app = Flask(__name__)    app.config.from_object(__name__)    flatpages = FlatPages(app)    # 首页    @app.route('/')    def index():        pass    # 文章列表    @app.route('/list/<string:tag>/')    def page_list(tag):        pass    # 文章详情    @app.route('/page/<string:uri>/')    def page(uri):        pass    if __name__ == '__main__':        app.run()       

上面是一个可以运行的微型博客的全部后端程序,几乎就是你现在正常访问的博客的全部,你看,非常简短!

如果你用过类似WordPress或者新浪博客等博客工具,显然有一个问题:哪儿可以添加新的文章和管理文章分类?的确,这段代码离一个传统的博客程序该有的全貌相差甚远,因为还欠缺一个管理后台。

以WordPress为例子,在一般情况下,如果访问如xxx.com,可以看到博客的前台,也就是各种博客文章。而访问如xxx.com/wp-admin 则可以进入到后台,用来管理文章和发布新文章。在路由的写法上,对于上面这个文件你可能要这样扩充一下功能(为了节省篇幅方便演示,下面代码详细部分省略,以 pass 代替详细部分)。

    # -*- coding: utf-8 -*-    # run.py    from flask import Flask, render_template, request    from flask_flatpages import FlatPages    FLATPAGES_AUTO_RELOAD = True    FLATPAGES_ROOT = 'pages'    FLATPAGES_EXTENSION = '.md'    app = Flask(__name__)    app.config.from_object(__name__)    flatpages = FlatPages(app)    @app.route('/')    def index():        pass  # 为了方便演示这里省略详细代码    @app.route('/list/<string:tag>/')    def page_list(tag):        pass    @app.route('/page/<string:uri>/')    def page(uri):        pass      # 新增的后台部分代码    @app.route('/admin/login/')    def admin_login():        pass          @app.route('/admin/page/')    def admin_pages():        pass           @app.route('/admin/page/new/')    def new_page():        pass      @app.route('/admin/page/edit/')    def edit_page():        pass                if __name__ == '__main__':        app.run()  

上述代码新增加了管理后台部分,具体是增加了一个后台登录界面、文章列表以及新增和编辑文章的功能共四个部分。

继续上述思路,可以想到新的几个问题:

1)一般情况下,前台和后台用两套模板。或者通俗的讲,前台费力弄得好看点,后台反正自己用,能用就成,丑点无所谓。那么怎么让前台和后台用两套模板? 
2)后台部分逻辑比前台复杂,还需要导入新的包,如果和前台写在一个文件里,后面修改会不会容易出错,例如本来改后台部分结果牵连前台出问题? 
3)既然Python力求简洁,那代码能否再简洁些?比如新增的路由参数 /admin 重复写了4遍,能不能对后台定义一个前缀,后台部分的自动加这个/admin ? 
4)如果这个博客程序需要多人来维护,多人编辑同一个文件去提交时冲突如何解决?


亦或者你还有其他的一些疑问,如果是关乎怎么把程序做大的同时,还能保证简洁、良好、易于维护的代码组织结构,一个容易想到的方向就是程序的「模块化」。

在你学习Python的过程中,早已见识到了Python模块化,比如Python的包概念,也即你总是能看到的 import …… 引入的那些东西和本身的这个引入方法。那么,对于Flask而言,你也许会举一反三的把博客的后台程序部分抽离出来,单独编写一个文件,然后再 import …… ,这样不就模块化了?!

但是等等,程序跑不起来了?还有,前面刚提到过的四个问题,似乎这样做之后只是勉强解决了第四个问题,前三个呢?

所以,可想而知,我们的确需要一个模块化的方法,这个思路的方向本身不错,要点在于我们需要的是一个Flask认可的、兼容的、支持的模块化方法。Flask的作者作为一个老江湖早就考虑到这点,并提供了一个名为Blueprint的方法来让你实现模块化组织程序结构。

Blueprint中文的翻译现在有两种常见的:蓝图以及蓝本。这里我们称蓝图好了。

对于上述程序,我们应用蓝图方法修改之后,大致是下面这样了。

首先,我们新增一个文件adminPages.py,如下:

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

同时,改写run.py 如下:

    # -*- coding: utf-8 -*-    # run.py    from flask import Flask, render_template, request    from flask_flatpages import FlatPages    FLATPAGES_AUTO_RELOAD = True    FLATPAGES_ROOT = 'pages'    FLATPAGES_EXTENSION = '.md'    app = Flask(__name__)    app.config.from_object(__name__)    flatpages = FlatPages(app)    @app.route('/')    def index():        pass  # 为了方便演示这里省略详细代码    @app.route('/list/<string:tag>/')    def page_list(tag):        pass    @app.route('/page/<string:uri>/')    def page(uri):        pass      # 新增的后台部分代码    from adminPages import admin    app.register_blueprint(admin, url_prefix='/admin')        if __name__ == '__main__':        app.run()  

好,这就完成了一个应用蓝图的简单例子。让我们再来回顾上述代码,看看都做了些什么。

首先,我们新增了一个adminPages.py的文件,并在文件中导入了Flask的蓝图方法Blueprint。

紧接着,我们用admin实例化了一个蓝图应用,就是这句:

admin = Blueprint('admin', __name__)

Blueprint要求至少传入两个参数,分别是蓝图的名字和蓝图所在的包或模块。

我们将后台部分独立出来作为蓝图模块,并取名为 admin ,所以我们传入第一个参数'admin'。

紧接着是所在的包或模块,如果你有印象,大概还记得Python有一个特殊属性_ name _ ,当用在一个文件里时,代表的是模块(或包)的名字,所以第二个参数传入 _ name _ 。

因为使用了蓝图,原来的路由 @app.route() 改写成了 @admin.route(),改写的原因你需要看一下官方文档了解更为深入的细节,这里暂且不表。

对于run.py,我们剥离出了 admin 部分的程序代码,但在文件末尾,又导入了蓝图模块,然后按照Flask蓝图的用法去注册了蓝图,就是这两行代码:

from adminPages import admin  app.register_blueprint(admin, url_prefix='/admin')

其中,app.register_blueprint()的第一个参数无需过多解释,第二个参数 url_prefix= 即在定义前缀。还记得前面的四个问题吗?这里针对的就是第三个问题。再回过头去看看,你会发现adminPages.py里,原来路由里的 /admin 都去掉了。

就是这些,我们简单的应用了一把Flask的蓝图功能,一定程度上算是解决了前面四个问题中的三个,还有一个两套模板的问题蓝图也支持,并且十分简单,留给你去看看官方文档了解吧。

原创粉丝点击