前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flask(9)- 蓝图的基本使用

Flask(9)- 蓝图的基本使用

作者头像
小菠萝测试笔记
发布2021-07-16 10:39:00
7680
发布2021-07-16 10:39:00
举报

前言

  • 在前面的例子中,所有的页面处理逻辑都是放在同一个文件中,随着业务代码的增加,将所有代码都放在单个程序文件中是非常不合适的
  • 不仅会让阅读代码变得困难,而且会给后期维护带来麻烦
  • Flask 中使用蓝图,提供了模块化管理程序路由的功能,使程序结构更加清晰

蓝图简介

  • 随着 Flask 程序越来越复杂,需要对程序进行模块化的处理
  • 蓝图 (Blueprint) 是 Flask 程序的模块化处理机制
  • 它是一个存储视图方法的集合
  • Flask 程序通过 Blueprint 来组织 URL 以及处理请求
Blueprint 具有以下属性
  • 一个项目可以具有多个 Blueprint
  • Blueprint 可以单独拥有自己的模板、静态文件的目录
  • 在应用初始化时,注册需要使用的 Blueprint

基本用法

功能概述

假设网站包含有如下 4 个页面:

页面

功能

处理函数

/news/society/

社会新闻版块

society_news

/news/tech/

IT 新闻版块

tech_news

/products/car/

汽车产品版块

car_products

/products/baby/

婴幼儿产品版块

baby_products

  • 前两个都是 /news 前缀,可以组成一个蓝图 news
  • 后两个是 /products 前缀,可以组成一个蓝图 products
  • 相当于四个视图函数,两个蓝图

程序中包含 4 个视图函数,根据页面路径,Flask 将请求转发给对应的视图函数,从浏览器发送过来的请求的处理过程如下图所示

使用蓝图后,路由匹配流程

  1. 浏览器访问路径 /products/car
  2. Flask 框架在蓝图 news 和蓝图 products 中查找匹配该页面路径的路由
  3. 发现在蓝图 products 中,存在和路径 /products/car 匹配的视图函数 car_products
  4. 最后将请求转发给函数 car_products 处理

实战小栗子

目录结构

例子程序包括 2 个蓝图,由 3 个文件构成:

  • app.py,程序的主文件;
  • news.py,实现蓝图 news;
  • products.py,实现蓝图 products。

app.py 代码

代码语言:javascript
复制
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/7/12 8:36 下午
# file: app.py
"""

# 导入 Flask 和 蓝图 Blueprint
from flask import Flask, Blueprint

# 导入蓝图类
from s7_blueprints import news
from s7_blueprints import products

app = Flask(__name__)

# 注册蓝图
app.register_blueprint(news.blueprint)
app.register_blueprint(products.blueprint)

if __name__ == '__main__':
    app.run(debug=True)

news.py 代码

代码语言:javascript
复制
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/7/12 8:36 下午
# file: news.py
"""

# 导入蓝图
from flask import Blueprint

"""
实例化蓝图对象
第一个参数:蓝图名称
第二个参数:导入蓝图的名称
第三个参数:蓝图前缀,该蓝图下的路由规则前缀都需要加上这个
"""
blueprint = Blueprint('news', __name__, url_prefix="/news")


# 用蓝图注册路由
@blueprint.route("/society/")
def society_news():
    return "社会新闻板块"


@blueprint.route("/tech/")
def tech_news():
    return "新闻板块"

注意:页面的绝对路径是 /news/society/ 和 /news/tech/,因为蓝图的 url_prefix 设置为 news,在蓝图内部,页面的相对路径是 /society/ 和 /tech/

products.py 代码

代码语言:javascript
复制
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/7/12 8:36 下午
# file: products.py
"""

from flask import Blueprint

blueprint = Blueprint("products", __name__, url_prefix="/product")


@blueprint.route("/car")
def car_products():
    return "汽车产品版块"


@blueprint.route("/baby")
def baby_products():
    return "婴儿产品版块"

注意:页面的绝对路径是 /products/car/ 和 /product/baby/,因为蓝图的 url_prefix 等于 products,在蓝图内部,页面的相对路径是 /car/ 和 /baby/

postman 发起请求的结果

更具扩展性的架构

概述

随着业务代码的增加,需要为 Flask 程序提供一个具备扩展性的架构,根据 Flask 程序的扩展性分为如下三种类型:

1、所有的页面逻辑放在同一个文件中

在这种架构中,程序完全不具备扩展性

在初学 Flask 时,使用的栗子都是这种类型

2、使用一个独立的 Python 文件实现蓝图

在这种架构中,程序具备一定的扩展性:

  • 程序由主程序和多个蓝图构成
  • 每个蓝图对应一个 Python 文件
  • 所有的蓝图共享相同的模板文件目录
  • 所有的蓝图共享相同的静态文件目录

上面的栗子就是采用这种架构

程序包含 2 个蓝图: news 和 products,由 3 个文件构成:app.pynews.pyproducts.py,其中 news.py 实现新闻版块,products.py 实现产品版块

3、使用一个独立的目录实现蓝图

在这种架构中,程序的扩展性最好:

  • 程序由主程序和多个蓝图构成
  • 每个蓝图对应一个独立的目录,存储与这个蓝图相关的文件
  • 每个蓝图有一个独立的模板文件目录
  • 每个蓝图有一个独立的静态文件目录

模板文件寻找规则

每个蓝图可以拥有独立的模板文件目录,模板文件寻找规则如下:

  • 如果项目中的 templates 文件夹中存在相应的模板文件,则使用 templates 文件夹下的模板文件;
  • 如果项目中的 templates 文件夹中没有相应的模板文件,则使用定义蓝图的时候指定的 templates 文件夹下的模板文件
  • 项目中的 templates 文件夹优先级大于指定的 templates 文件夹

静态文件寻找规则

每个蓝图可以独立的静态文件目录,静态文件寻找规则如下:

  • 如果项目中的 static 文件夹中存在相应的静态文件,则使用 static 文件夹下的静态文件
  • 如果项目中的 static 文件夹中没有相应的静态文件,则使用定义蓝图的时候指定的 static 文件夹下的静态文件
  • 项目中的 templates 文件夹优先级大于指定的 templates 文件夹

究极扩展性的栗子

目录结构

目录功能描述

路径

功能描述

templates

项目默认的模板文件夹

static

项目默认的静态文件夹

news

蓝图 news 的相关文件

news/templates

蓝图 news 的私有模板文件夹

news/static

蓝图 news 的私有静态文件夹

products

蓝图 products 的相关文件

products/templates

蓝图 products 的私有模板文件夹

products/static

蓝图 products 的私有静态文件夹

文件功能描述

路径

功能描述

app.py

主程序

news/__init.py__

蓝图 news 的实现

news/templates/society.html

属于蓝图 news 的一个模板文件

news/static/news.css

属于蓝图 news 的一个静态文件

products/__init.py__

蓝图 products 的实现

app.py 的代码

代码语言:javascript
复制
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/7/12 10:39 下午
# file: 7_blueprint_app.py
"""

from flask import Flask

from s7_news import news
from s7_product import products

app = Flask(__name__)

app.register_blueprint(news.blueprint)
app.register_blueprint(products.blueprint)

app.run(debug=True)

news/__init.py__ 的代码

代码语言:javascript
复制
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/7/12 8:36 下午
"""

# 导入蓝图
from flask import Blueprint, render_template

"""
实例化蓝图对象
第一个参数:蓝图名称
第二个参数:导入蓝图的名称
第三个参数:蓝图前缀,该蓝图下的路由规则前缀都需要加上这个
"""
blueprint = Blueprint('news', __name__, url_prefix="/news", template_folder="templates", static_folder="static")


# 用蓝图注册路由
@blueprint.route("/society/")
def society_news():
    return render_template('society.html')


@blueprint.route("/tech/")
def tech_news():
    return "IT 新闻板块"
  • 蓝图中页面的 URL 前缀为 /news;
  • 蓝图的模板目录为 templates,绝对路径为 ‘项目目录 /news/templates’;
  • 蓝图的静态文件目录为 static,绝对路径为 ‘项目目录 /news/static’
  • 调用 render_template (‘society.html’) 渲染模板文件 society.html,根据模板文件的查找规则,最终在 ‘项目目录 /news/templates’ 目录下找到模板文件

news/templates/society.html 的代码

代码语言:javascript
复制
<link rel="stylesheet" href="{{ url_for('news.static',filename='news.css')}}">
<h1>社会新闻</h1>

在模板文件中引用了静态文件 news.css。{{url_for (‘news.static’,filename=‘news.css’) }} 的输出为 news/static/news.css,其中 news.static 表示蓝图 news 的 static 目录

news/static/news.css 的代码

代码语言:javascript
复制
h1 {
    color: red;
}

product.py/__init.py__ 的代码

代码语言:javascript
复制
from flask import Blueprint

blueprint = Blueprint('products', __name__, url_prefix='/products')

@blueprint.route("/car")
def car_products():
    return "汽车产品版块"

@blueprint.route("/baby")
def baby_products():
    return "婴儿产品版块" 

浏览器访问效果

访问 http://localhost:5000/news/society/

验证目录优先级

在根目录下的 templates 目录下也添加一个 society.html 文件,在根目录下的 static 目录下添加一个 project.css

html 代码
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<link rel="stylesheet" href="{{ url_for('static',filename='project.css') }}">
<h1>社会新闻啊啊啊</h1>
</body>
</html>
css 代码
代码语言:javascript
复制
h1 {
    color: blue;
}
预期结果
  • 根据 templates、static 的查找规则,会优先查找项目根目录的 templates、static 目录下是否有对应的模板文件、静态文件
  • 这里 society.html 同时出现在根目录的 templates 和蓝图目录的 templates,应该优先返回根目录的 templates 下的 society.html
浏览器访问效果

符合预期结果

Blueprint 源码解析

类初始化 __init__ 方法参数列表

  • name:蓝图名称,将会被添加到每个 endpoint
  • import_name:蓝图包的名称,通常是 __name__,有助于找到 root_path 蓝图
  • static_folder:包含静态文件的文件夹,由蓝图的静态路由提供服务,路径以蓝图文件为根路径开始找
  • static_url_path:提供静态文件的 url,默认就是 static_folder,如果蓝图没有 url_prefix,应用程序的静态路由将优先,并且蓝图的静态文件将无法访问
  • template_folder:包含模板文件的文件夹,路径以蓝图文件为根路径开始找
  • url_prefix:会作为蓝图所有路由的前缀路径
  • subdomain:蓝图路由将匹配的子域
  • url_defaults:蓝图路由的默认值字典
  • root_path:默认情况下,蓝图会自动设置这基于“import_name”
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-07-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 蓝图简介
    • Blueprint 具有以下属性
    • 基本用法
      • 功能概述
        • 使用蓝图后,路由匹配流程
        • 实战小栗子
          • 目录结构
            • app.py 代码
              • news.py 代码
                • products.py 代码
                  • postman 发起请求的结果
                  • 更具扩展性的架构
                    • 概述
                      • 1、所有的页面逻辑放在同一个文件中
                      • 2、使用一个独立的 Python 文件实现蓝图
                      • 3、使用一个独立的目录实现蓝图
                    • 模板文件寻找规则
                      • 静态文件寻找规则
                      • 究极扩展性的栗子
                        • 目录结构
                          • 目录功能描述
                          • 文件功能描述
                        • app.py 的代码
                          • news/__init.py__ 的代码
                            • news/templates/society.html 的代码
                              • news/static/news.css 的代码
                                • product.py/__init.py__ 的代码
                                  • 浏览器访问效果
                                    • 验证目录优先级
                                      • html 代码
                                      • css 代码
                                      • 预期结果
                                      • 浏览器访问效果
                                  • Blueprint 源码解析
                                    • 类初始化 __init__ 方法参数列表
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档