1、蓝图
对于简单的项目来说,比如项目就只有一个user模块,我们可以都将视图函数定义在一个文件里面,不需要用到蓝图。
但是如果我们的项目有多个模块,如下有v1模块,v2模块.....等,那么如果我们将这么多的模块的视图文件都杂在一个文件中去写的话,就会导致管理非常不便:
如多人开发不同模块,会导致业务代码经常出现冲突,或者我们要弃用某个功能模块的话,需要去文件中找到所有的相关功能代码并一一删除......
这样子做虽然没错,但是非常不符合pythonic的优雅,简洁的特性。
根据pythonic的特性,我们肯定希望尽可能的将代码模块化,使我们的代码看起来更加的整洁和优雅,这时候flask的Blueprint就派上用场了。
如下,我们的package api下面有两个模块,v1和v2,我们可以分别在v1和v2的__init__.py中,定义两个蓝图v1和v2,然后在v1和v2下面的文件中分别使用自定义的v1 v2两个蓝图去实现相关路由
即蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和url相互关联的功能。
蓝图的实现方式如下:
from flask import Blueprint
def create_blueprint():
v1 = Blueprint("v1", __name__) # v1是自定义的蓝图的名称, __name__表示当前模块名称,此处也可以指明每个模块下面的静态文件和模板路径template_folder="", static_folder=""
return v1
创建完成v1蓝图后,我们需要在实例化flask核心对象app时,将其注册到flask核心对象app上
def register_blueprint(app):
from app.api.v1 import create_blueprint
bp_v1 = create_blueprint()
app.register_blueprint(bp_v1, url_prefix="/v1") # url_prefix是给注册的蓝图添加路由前缀。
def instance_app():
app = Flask(__name__)
register_blueprint(app)
return app
然后我们就可以在v1下面的book和user中使用我们的blueprint了。
2、红图
蓝图主要是用于模块级别的区分,并不适用于函数级别的区分的,如下图,对于每个模块下面都有不同的视图函数,为了区分这些不同的视同函数,我们需要自定义一个和蓝图有着相同功能的模块。这里为了体现它和蓝图的异曲同工之妙,我们称之为红图(redprint)
红图(redprint)的实现:
既然红图的功能和蓝图一样,那么红图的实现,我们自然可以参考蓝图的实现方式:
class Redprint():
def __init__(self, name):
self.name=name
self.mond = [] # 定义mond的作用在于,存储每个绑定到红图上的function,url,options等
def route(self, url, **options): # 参考蓝图的使用,@bp_v1.route(url, method=["GET", "POST"])
def decorate(f): # 装饰器的本质,就是对闭包的调用
self.mond.append((f, url, options))
return f
return decorate
def register(self, bp, url_prefix=None)
if url_prefix is None:
url_prefix = "/"+self.name
for f, url, options in self.mond:
endpoint = options.pop("endpoint", f.__name__) # 从options关键字参数中,取出endpoint,如果没有传递endpoint参数,则使用被装饰的方法名称作为endpoint
bp.add_url_rule(url_prefix+url, endpoint, f, **options)
红图的使用:
在定义了红图实现类后,还是是上面的项目结构,在v1和v2包下的book和user视图函数中分别使用红图(以book为例)
api = Redpint("book")
@api.route("get")
def get_book():
return "get book"
最后,需要将红图注册到蓝图上:
在上面的创建蓝图的函数中,注册红图:
from app.api.v1 import book, user
def create_blueprint():
bp_v1 = Blueprint("v1", __name__)
book.api.register(bp_v1)
user.api.register(bp_v1)
这样,要在浏览器中输入ip:post/v1/book/get 即可访问v1下面的book中的get_book视图函数了