1.1 初始化项目
1. 一个项目的初始化流程如下:
image.png
2. 新建入口文件
- app/app.py
- from flask import Flask
- __author__ = "gaowenfeng"
- def create_app():
- app = Flask(__name__)
- app.config.from_object('app.config.secure')
- app.config.from_object('app.config.setting')
- return app
- ginger.py
- from app.app import create_app
- __author__ = "gaowenfeng"
- app = create_app()
- if __name__ == '__main__':
- app.run(debug=True)
1.2 红图
1. 蓝图拆分视图函数的缺陷的缺陷
1. 蓝图的作用并不是用来拆分视图函数的, 而是用来拆分模块的
2. 使用蓝图, 统一个业务模型的试图函数的前缀都一样, 代码重复啰嗦
2. 打开思维, 创建自己的 redprint - 红图
为了解决上面的两个问题, 我们可以模仿蓝图, 构建一个自定义的对象 - 红图, 红图的定位是用来拆分视图, 也就是视图函数层
image.png
我们采用自顶向下的编程思想, 先编写 redprint 在试图函数中的使用代码, 再编写 redprint 具体的实现
2.1 视图函数向红图的注册
- app/api/v1/book.py
- from app.libs.redprint import RedPrint
- __author__ = "gaowenfeng"
- api = RedPrint('book')
- @api.route('/get')
- def get_book():
- return 'get book'
- @api.route('/create')
- def create():
- return 'create book'
- app/api/v1/user.py
- from app.libs.redprint import RedPrint
- __author__ = "gaowenfeng"
- api = RedPrint('user')
- @api.route('/get')
- def get_user():
- return 'i am gwf'
2.2 红图向蓝图的注册
- app/api/__init__.py
- from flask import Blueprint
- from app.api.v1 import book, user
- __author__ = "gaowenfeng"
- def create_blueprint_v1():
- bp_v1 = Blueprint('v1', __name__)
- # 假设 api 有 register 的方法, 后面再实现, url_prefix 解决前缀问题
- book.api.register(bp_v1, url_prefix='/book')
- user.api.register(bp_v1, url_prefix='/user')
- return bp_v1
2.3 蓝图向 Flask 核心对象的注册
- app/app.py
- from flask import Flask
- __author__ = "gaowenfeng"
- def register_blueprint(app):
- from app.api.v1 import create_blueprint_v1
- # url_prefix 定义 url 前缀
- app.register_blueprint(create_blueprint_v1(), url_prefix='/v1')
- def create_app():
- app = Flask(__name__)
- app.config.from_object('app.config.secure')
- app.config.from_object('app.config.setting')
- register_blueprint(app)
- return app
3. 实现 Redprint
因为我们的红图的作用就是要代替蓝图来实现试图函数的拆分, 所以功能实现上可以参考蓝图的实现.
3.1 装饰性 route 的实现
蓝图的实现
- def route(self, rule, **options):
- """Like :meth:`Flask.route` but for a blueprint. The endpoint for the
- :func:`url_for` function is prefixed with the name of the blueprint.
- """
- def decorator(f):
- # 获取 endpoint, 默认为试图函数名
- endpoint = options.pop("endpoint", f.__name__)
- # 注册视图函数
- self.add_url_rule(rule, endpoint, f, **options)
- return f
- return decorator
红图的实现可以模仿蓝图的实现结构 , 由于红图的 route 里没有办法拿到蓝图的对象, 所以我们可以先把他们存储起来, 等碰到的时候再进行注册
- class Redprint:
- def __init__(self, name):
- self.name = name
- self.mound = []
- def route(self, rule, **options):
- def decorator(f):
- self.mound.append((f, rule, options))
- return f
- return decorator
3.2 register 方法
在 register 方法中可以获取到蓝图对象, 所以之前 route 中视图函数的注册延迟到这里进行
- def register(self, bp, url_prefix=None):
- # 如果不传 url_prefix 则默认使用 name
- if url_prefix is None:
- url_prefix = '/'+self.name
- # python 的自动拆包
- for f, rule, options in self.mound:
- endpoint = options.pop("endpoint", f.__name__)
- # 将视图函数注册到蓝图上来
- bp.add_url_rule(url_prefix + rule, endpoint, f, **options)
来源: http://www.jianshu.com/p/1890ff4655f7