zoukankan      html  css  js  c++  java
  • flask组件化开发:蓝图

    Flask 蓝图介绍

    蓝图也就是 BluePrint 是 Flask 提供的一个类,它具备 Flask 核心对象的很多功能,其中最重要的就是注册路由,我们通过蓝图,可以将视图函数根据不同的功能拆分到不同的模块中,从而实现对视图函数的模块化管理与开发。

    简单来说,我们可以把蓝图认为是一个完整 Web 应用的一部分,以个人Blog为例,它可以有Blog的展示部分,也需要有后台部分,此外还有登陆的部分,这些不同的部分就可以通过蓝图来进行拆分管理,它们组合起来就是一个完整的 Web 应用。

    创建蓝图

    先不忙创建蓝图,既然蓝图的作用是分模块存放视图函数,那么我们肯定需要创建 Python 模块以及 Python 包,本文所用的示例结构是如下这样的:

    .
    ├── demo # 应用包
    │ ├── __init__.py
    │ └── blueprints # 蓝图包
    │ ├── home.py # 首页蓝图模块
    │ ├── admin.py # 后台蓝图模块
    │ └── __init__.py
    └── app.py # 入口文件

    接下来,就可以创建蓝图了,在 home.py 中增加如下代码:

    # demo/blueprints/home.py
    from flask import Blueprint
     
    home = Blueprint("home", __name__, url_prefix="/home")
     
    @home.route('/')
    def index():
    return "This is home index page."

    上面的代码中,我们首先实例化了一个 Blueprint 对象,和实例 Flask 核心对象不同,Blueprint 多了两个额外的参数:

    • "home": 蓝图的名称,这是一个必须的参数,之前在 Flask 路由与视图函数 一文的路由机制中,我专门谈到了 Flask 中 endpoint 端点的作用,这里的蓝图名称就是构成视图函数 endpoint 的一部分。
    • url_prefix="/home": 该蓝图下所有路由的前缀地址,比如这里定义的前缀是 /home,那么如果这个蓝图下有一个 /hello 路由,那么它的完整 URL 地址就是这样的 127.0.0.1:5000/home/hello,这里要注意的是,url_prefix 并非是必须的参数,我们也可以在注册蓝图的时候定义前缀地址,后面会提到。

    除了上面这些,蓝图在注册路由方面和 Flask 核心对象是一模一样的,因为蓝图在注册路由的时候调用的也是 add_url_rule 这个方法,只不过此时这个方法并不是来自 Flask 核心对象了。

    注册蓝图

    注册蓝图就比较简单了,在 app.py 中,添加如下代码:

    # app.py
    from flask import Flask
     
    from demo.blueprints.home import home
     
    app = Flask(__name__)
     
    # 注册蓝图
    app.register_blueprint(home)

    注册蓝图只需要调用 Flask 核心对象的 register_blueprint 方法即可。

    接着我们就可以测试一下效果了,在命令行启动 Flask 服务:

    $ export FLASK_APP=app.py
    $ export FLASK_ENV=development
    $ flask run

    访问 http://127.0.0.1:5000/home/ 可以看到如下页面:

    Flask 入门 6 —— Flask 蓝图详解 (Flask Blueprint) 1

    注册蓝图时设置 URL 前缀

    前面创建蓝图的时候,url_prefix 是定义在了实例化 Blueprint 的时候,除了这种方式,我们还可以在注册蓝图的时候定义 url_prefix,首先把实例化蓝图时定义的 url_prefix 删除掉:

    ...
    # 删除 url_prefix
    home = Blueprint("home", __name__)
    ...

    接着在注册蓝图的时候,添加 url_prefix 参数

    ...
    # 注册蓝图时设置 url_prefix 参数
    app.register_blueprint(home, url_prefix="/home")
    ...

    不管是在注册蓝图的时候设置 url_prefix 还是在实例化蓝图的时候设置,这两种方式的结果都是一样的,在编写代码的时候选择其中一种即可,不过如果蓝图特别特别多或者你比较习惯 Django 那种路由管理模式那么在注册蓝图的时候设置 url_prefix 是个好选择,毕竟如果蓝图多了的话修改某些蓝图的 URL 前缀肯定是在一个统一的地方比较方便。

    endpoint 端点

    在继续接下来的内容之前,我想在这里演示一下 Flask 对于 endpoint 的处理。

    上面我们已经定义了一个蓝图,并且注册了一个路由,接下来在 admin.py 中,我们再定义一个蓝图并为其注册一个路由。

    # demo/blueprints/admin.py
    from flask import Blueprint
     
    admin = Blueprint("admin", __name__, url_prefix="/admin")
     
    @admin.route("/")
    def index():
    return "This is admin index page."

    然后把这个蓝图注册给 Flask 核心对象

    # app.py
    from flask import Flask
     
    from demo.blueprints.home import home
    from demo.blueprints.admin import admin
     
    app = Flask(__name__)
     
    app.register_blueprint(home)
    app.register_blueprint(admin)

    此时就有了两个蓝图,这两个蓝图中都有一个视图函数 index ,之前在 Flask 路由与视图函数 这篇文章中,我就提到 Flask 通过 endpoint 来指向视图函数,这种机制是为了避免视图函数在命名空间上的冲突,下面到 flask shell 中,执行如下代码:

    $ flask shell
     
    In [1]: from app import app
    In [2]: app.url_map
    Out[2]:
    Map([<Rule '/admin/' (GET, OPTIONS, HEAD) -> admin.index>,
    <Rule '/home/' (GET, OPTIONS, HEAD) -> home.index>])

    通过 url_map 属性可以查询到当前的 Flask 应用所有的路由地址和其指向的 endpoint,在这里我们可以看到,当前的 Flask 应用一共有两个 URL :

    • /admin/ 是 URL 相对路径。
    • admin.index 就是 endpoint 了。

    这里的重点是 URL 路径所指向的 endpoint,它是由蓝图的名称和视图函数名称共同构成的,如果没有 endpoint 当用户请求 http://127.0.0.1:5000/home/ 或者 http://127.0.0.1:5000/admin/ 的时候,因为存在两个 index 视图函数,直接通过 URL 找视图函数就出问题了,到底哪个 index 函数对应的是用户所请求 URL ?所以 Flask 才需要 endpoint 这种机制来处理 URL 和视图函数之间的映射。

    蓝图资源

    蓝图除了可以将路由模块化,一样也可以将对应的静态文件和模板模块化,在演示蓝图处理自身静态资源之前,我们还需要对当前的目录结构做一些改动,将我们之前创建的两个蓝图模块移动到各自对应的文件夹中,接着在 home 目录下创建 templates 和 static 目录用来存放该蓝图下的模板文件和静态文件,最后在 templates 目录下创建 index.html 并在 static 目录下创建 main.css

    .
    ├── demo
    │ ├── __init__.py
    │ └── blueprints
    │ ├── __init__.py
    │ ├── admin
    │ │ ├── __init__.py
    │ │ └── admin.py
    │ └── home
    │ ├── __init__.py
    │ ├── templates # 模板目录
    │ └── home
    │ └── index.html
    │ ├── static # 静态资源目录
    │ │ ├── main.css
    │ └── home.py
    └── app.py

    接下来,还需要简单的改动一下 app.py 中的引用:

    # app.py
    from flask import Flask
     
    from demo.blueprints.home.home import home
    from demo.blueprints.admin.admin import admin
    ...

    最后分别在 index.html 和 main.css 添加下面的代码

    <!-- demo/blueprints/home/templates/home/index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>This is home index page.</h1>
    </body>
    </html>
    /* demo/blueprints/home/static/main.css */
    h1 {
    color: orange;
    font-style: italic;
    }

    做好准备工作,就可以演示蓝图使用自身的模板和静态文件了。

    蓝图模板

    首先看下模板的使用,要想让蓝图正确的识别到这个模板,首先需要配置蓝图的模板路径,在实例化蓝图的时候,通过 template_folder 参数指定模板路径:

    from flask import Blueprint, render_template
     
    # 添加 template_folder 参数指定模板路径
    home = Blueprint("home", __name__, url_prefix="/home",
    template_folder="templates")
     
    @home.route('/')
    def index():
    return render_template("home/index.html")

    上述代码中,指定的模板路径是一个相对路径,这个路径是基于蓝图实例根目录的;此外在创建模板目录的时候,我特地在 templates 目录下多创建了一个 home 目录保存 index.html 这也是有原因的,如果 app.py 根目录下还有一个 templates 全局模板目录,而其中也有一个 index.html,那么此时全局的 index.html 的优先级是高于蓝图模板的优先级的,所以如果不添加一个 home 目录来区分蓝图模板和全局模板,那么 render_template("index.html") 这段代码会优先去使用 templates 下的 index.html

    当然如果全局的 templates 目录下,也有 home 目录,也存在 index.html,那么还是会覆盖蓝图的 templates/home/index.html,所以这里就引发了是否有必要为蓝图单独创建模板目录的问题了,毕竟我们完全可以在全局 templates 目录中,通过文件夹的形式区分模板所属的蓝图,不过这个问题是仁者见仁的事情,我个人是不倾向于给蓝图单独指定模板目录的。

    蓝图静态文件

    演示了蓝图模板,再来看看蓝图的静态文件,蓝图独有的静态文件也需要和模板一样指定静态文件目录的路径:

    ...
     
    # 添加 static_folder 参数指定静态文件路径
    home = Blueprint("home", __name__, url_prefix="/home",
    template_folder="templates",
    static_folder="static")
     
    ...

    通过 static_folder 即可设置蓝图的静态文件路径,和模板路径的设置差不多,指定相对路径即可。

    接着,到 index.html 中,我们需要引用静态文件了:

    ...
    <head>
    ...
    <link rel="stylesheet" href="{{ url_for('home.static', filename='main.css') }}">
    </head>
    ...

    和引用全局静态文件不同,引用蓝图独有的静态文件时,我们需要指定蓝图的前缀 home.static,这样 Flask 才会正确的前往蓝图的 /static 下寻找静态文件;此外和模板不同的是,蓝图不存在优先级的问题,指定了前缀之后,它就只会在蓝图中搜索静态文件。

    最后,看一眼网页,我们单独为蓝图设置的模板和静态文件工作的还是正常的:

    Flask 入门 6 —— Flask 蓝图详解 (Flask Blueprint) 2

    转载:https://www.hizxc.com/1563.html#zhu_ce_lan_tu

     
  • 相关阅读:
    IE浏览器请求数据是提示下载的问题
    jS清除浏览器缓存
    JS获取时间戳
    keycode
    JS简单解决并发量
    写移动端流氓方法,无意看到,分享下
    CSS中的rem的换算
    jsp会话监听
    jsonp在jsp中的使用
    Java中的位运算符
  • 原文地址:https://www.cnblogs.com/-wenli/p/13925278.html
Copyright © 2011-2022 走看看