Python - Flask 无脑学习实践 (三)Flask Blueprint 使用和运行的简单说明

这里有两种可以使用 BluePrint 的方法
  1. Folder as working URI 使用文件夹作为一个对应的 URI 的访问路径。http://test.com/api 中 api 对应项目中的一个文件夹
  2. File as working URI 使用文件作为一个对应的URI 访问路径。http://test.com/api 中 api 对应项目中的一个文件.py

Case 1- Folder as working URI

当前目录文件

./app
├── main (主体模块:主要定义 uri 和 逻辑的 blueprint py 文件)
│   ├── main.py
├── static(静态文件目录:css)
├── templates(模版文件目录:通用 html )
├── app.py
建立 blueprint 的步骤
  1. 创建一个蓝图的包,其实已经创建了 为main, 作为主要的Web 业务的包,建立蓝图对象 __init__.py
from flask import Blueprint
main = Blueprint('main',__name__)
  1. 建立一个 views.py 用来保存蓝图使用的视图view
from . import main

@main.route('/')
def home():
    return 'index.html'
  1. 在 __init__.py 中引入,新建的 views.py
from flask import Blueprint

main = Blueprint('main',__name__)

from . import views
  1. 在主应用 main.py 文件中的 main 对象上注册这个main blueprint 对象
from main import main
app.register_blueprint(blueprint=main,url_prefix='/main')

现在的app.py 如下

# /app/app.py
from flask import Flask, Response
import os
# 用户应用的 目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

from main.main import app_test

app = Flask(__name__)

@app.route('/')
def index():
    return Response('<h1>hello world. Will be replaced by Home</h1>')

# register blueprint , set url prefix
app.register_blueprint(blueprint=app_test, url_prefix='/api')

from main import main
app.register_blueprint(blueprint=main,url_prefix='/main')

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

上面的代码在启动的时候会报错:

AttributeError: module 'main.main' has no attribute 'name'

当我们点击进入查看源码的时候,Code 如下

if blueprint.name in self.blueprints:
            assert self.blueprints[blueprint.name] is blueprint, (
                "A name collision occurred between blueprints %r and %r. Both"
                ' share the same name "%s". Blueprints that are created on the'
                " fly need unique names."
                % (blueprint, self.blueprints[blueprint.name], blueprint.name)
            )

这就是一个Name Collision 的问题
使用了 app/main/__init__.py 和 /app/main.main.py 两个都标识了自己是 main
为了能继续使用当前的例子,注释掉 main.py
新的目录结构如下

./app
├── main (主体模块:主要定义 uri 和 逻辑的 blueprint py 文件)
│   ├──  main.py.bak
│   ├──  __init__.py
│   ├──  views.py
├── static(静态文件目录:css)
├── templates(模版文件目录:通用 html )
├── app.py

修改一下 app/app.py ,把有 conflict 的地方都注释掉

# /app/app.py
from flask import Flask, Response
import os
# 用户应用的 目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# from main.main import app_test # conflict 

app = Flask(__name__)

@app.route('/')
def index():
    return Response('<h1>hello world. Will be replaced by Home</h1>')

# register blueprint , set url prefix
# app.register_blueprint(blueprint=app_test, url_prefix='/api') # conflict

from main import main
app.register_blueprint(blueprint=main,url_prefix='/main')

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

程序跑起来咯
root python Flask 3
main python flask 3

运行机制[^1]

  • BluePrint 保存了一组将来可以在应用对象上执行的操作,注册路由 Route 就是一种路径操作
  • 当在app对象上调用 route 装饰器注册路由时,这个操作将修改对象的 url_map 路由表
  • 然而,蓝图对象根本没有路由表,当我们在蓝图对象上调用route装饰器注册路由时,它只是在内部的一个延迟操作记录列表defered_functions中添加了一个项 (博主不懂,无脑掠过)
  • 当执行app对象的 register_blueprint() 方法时,应用对象将从蓝图对象的 defered_functions 列表中取出每一项,并以自身作为参数执行该匿名函数,即调用应用对象的 add_url_rule() 方法,这将真正的修改应用对象的usr_map路由表 (博主不懂,无脑掠过)
    FROM:Flask-蓝图(blueprint)

Case 2 - File as working URI

在main 文件夹中加入2个新的文件 product 和 order

./app
├── main (主体模块:主要定义 uri 和 逻辑的 blueprint py 文件)
│   ├──  main.py.bak
│   ├──  __init__.py
│   ├──  views.py
│   ├──  login.py
│   ├──  order.py
├── static(静态文件目录:css)
├── templates(模版文件目录:通用 html )
├── app.py
# /app/main/login.py
__author__ = '1346478633@qq.com'
from flask import Blueprint,render_template

login = Blueprint('login',__name__)

@login.route('/')
def show():
    # return 'Login'
    return render_template('login.html') # add the html pages under templates
# /app/main/order.py
__author__ = '1346478633@qq.com'
from flask import Blueprint

'''
创建一个blueprint对象。第一个参数可看做该blueprint对象的姓名
在一个app里,姓名不能与其余的Blueprint对象姓名重复
第二个参数__name__用作初始化
'''
order = Blueprint('order',__name__)    

@order.route('/')           #将蓝图对象当做'app'那样使用
def login():
    return 'Order'

修改一下 app/app.py ,加入新的blueprint

# /app/app.py
from flask import Flask, Response
import os
# 用户应用的 目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# from main.main import app_test # conflict 

app = Flask(__name__)

@app.route('/')
def index():
    return Response('<h1>hello world. Will be replaced by Home</h1>')

# register blueprint , set url prefix
# app.register_blueprint(blueprint=app_test, url_prefix='/api') # conflict

from main import main
app.register_blueprint(blueprint=main,url_prefix='/main')

from main.login import login
app.register_blueprint(blueprint=login,url_prefix='/login')     # 将 main 模块里的蓝图对象account注册到app
from main.order import order
app.register_blueprint(blueprint=order,url_prefix='/order')     # 将 main 模块里的蓝图对象order注册到app

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

测试通过
order python flask 3
login python flask 3

运行机制
  1. app.py 文件运行,首先运行目录下面的 __init__.py 文件中的代码 (博主case2例子中没有使用)
  2. __init__ 文件导入Flask 以及 main 目录下面的py文件
  3. 接着 __init__ 或者 app 创建Flask对象
  4. 将 main 目录下面的模块文件注册到蓝图对象中
  5. app.py 最终运行的就是 __init__.py 和 app.py 中的代码 app 对象
Reference
  1. Flask-蓝图(blueprint)
  2. Python Flask 蓝图Blueprint
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值