咱们都知道 flask 是一个轻量级的 web 框架,相对于其余同类型框架更为灵活、轻便、安全且容易上手。开发者能够随意编写本身想要的项目结构,同时还有不少的第三方库供君选择。可是灵活的同时也带来了相应的问题,好比对不少初学者来讲,建的项目结构混乱,不易维护,还有经典的循环导入等问题python
不少初学者喜欢将启动文件和多个路由写在同一个文件中,例如如下代码:web
这样一旦随着视图函数的增多,代码的可维护性会变得愈来愈差。因此有必要对视图函数进行拆分。 咱们将其拆分红两个文件: run.py 和 view.py,其中 run.py 做为程序的启动文件,由于要将路由注册到 flask 核心对象上,因此在 view.py 中须要导入核心对象,同时 run.py 中要导入 view 最终,代码和项目结构以下所示:json
run.pyflask
# coding: utf-8
__author__ = 'Jerry'
from flask import Flask
app = Flask(__name__)
from app.web import view
@app.route("/")
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
复制代码
view.pyapi
# coding: utf-8
__author__ = 'Jerry'
from flask import request
from run import app
@app.route("/add")
def add():
name = request.args.get("name")
return f"Add {name}"
@app.route("/delete")
def delete():
name = request.args.get("name")
return f"Delete {name}"
@app.route("/change",methods=["POST"])
def change():
num = request.json
return f"change {num}"
复制代码
可是当我启动程序,在浏览器中输入地址 http://127.0.0.1:5000/add?name=Jerry 以后,报 404 Not Found。浏览器
而 127.0.0.1:5000/ 却能正常响应!安全
这是为何呢? 为何在 view.py 中注册的视图函数找不到呢? 缘由就是由于循环导入,咱们在 run.py 中导入了 view, 同时又在 view.py 中导入了 run.py 中的 app!最终致使什么结果呢,咱们经过调试来发现吧!app
因为,本次执行 __ name __ != __ main __,因此并不会执行 app.run()。那么程序将继续执行 view.py 中剩余代码框架
能够看到,程序将相关的路由函数注册到了 app2 上面! 当 view.py 中代码执行完成以后,将继续执行 run.py 中后面的代码。也就是前面提到的关键点 1 以后的相关代码!模块化
此时将路由函数 index 注册到了 app 上面,同时 __ name __ == __ main __,因此 app.run() 启动成功!
经过上面的分析,总结以下:
如今你应该明白了,view.py 中的视图函数注册的 app 和最终启动的 app 不是同一个,因此最终致使找不到视图函数!为了能有个更直观的感觉,咱们能够将 app 的内存地址打印出来,这样更加一目了然!
解决方案:Flask 给咱们提供一种机制,蓝图(Blueprint)。 蓝图就是一个存储操做路由映射方法的容器,主要用来实现客户端请求和 URL 相互关联的功能。 蓝图相似 Django 中的 app,二者的功能很是类似,帮助咱们实现模块化应用的功能。
在 Flask 中能够建立多个蓝图,表明不一样的功能模块。好比,上面代码中的 web 文件夹就能做为一个蓝图,另外用户相关的功能模块 user 也能建立一个相应的蓝图
了解蓝图的相关功能以后,咱们正式经过蓝图来解决以上问题。
# coding: utf-8
__author__ = 'Jerry'
from flask import Blueprint
api = Blueprint('api', __name__)
from app.web import view
if __name__ == '__main__':
pass
复制代码
# coding: utf-8
__author__ = 'Jerry'
from flask import request
from . import api
print(f"注册view中的app: {id(api)}")
@api.route("/add")
def add():
name = request.args.get("name")
return f"Add {name}"
@api.route("/delete")
def delete():
name = request.args.get("name")
return f"Delete {name}"
@api.route("/change", methods=["POST"])
def change():
num = request.json
return f"change {num}"
复制代码
因此在 app/__ init __.py 文件中作核心对象的初始化,同时将蓝图注册到核心对象上。代码以下:
同时在启动文件 run.py 记得导入 app 核心对象,修改后代码以下:
运行以后,咱们在浏览器中或者用代码来验证一下 GET 请求
POST 请求
完美!