在写任何 web 项目的时候路由的配置永远都是不可或缺的, 如 django 中的 include 方法 flask 中的 Blueprint 这些都是用于将多个 application 中的路由区别开来, 如果你要使用 restful 风格, 那么这种路由一定是必须做的, 很多教程在编写代码会在每一个视图函数上面写清楚完整的路径, 包括请求的参数, 以及请求的方法, 其实就是为了达到这样的目的
在 flask 中当一个庞大的系统中有很多小模块, 在分配路由的时候怎么处理呢? 全部都堆到一个 py 程序中, 调用 @App.route? 显然这是很不明智的, 因为当有几十个模块需要写路由的时候, 这样程序员写着写着自己就晕掉了. 同时也违背了面向对象设计原则中的控制反转原则. 模块与模块之间应该不要太紧密的依赖, 高级层级模块和低级层级的模块之间的依赖应该有一层抽象来实现.
Flask 框架中, 我们可以使用 blueprint 蓝图来解耦路由分配问题, 实现不同业务模块之间的较为松散的依赖.
blueprint 的实现
在相应的视图文件中编写
- from flask import Blueprint
- route_index = Blueprint('index_page',__name__)
- @route_index.route('/')
- def index():
- return 'hello wrold'
在主模块 views.py 文件中注册蓝图
- from Web.controllers.index import route_index #导入已经写好的蓝图
- from application import App #导入 App
- App.register_blueprint(route_index,url_prefix = '/')
- # 第一个参数: 表示注册的蓝图名
- # 第二个参数: 表示访问的路径
- # 这样在使用该路由装饰器的时候可以避免写多余的重复的路径
Blueprint() 函数解析, Blueprint 实际上是一个类
- def __init__(self, name, import_name, static_folder=None,
- static_url_path=None, template_folder=None,
- url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None):
- '''
- 其中 name,import_name 为必填参数, 其余是可选参数, 不填为 None 值
- url_prefix: 路由前缀
- 例如: 想到达 http://goods/article/first
- 在这个路由中 goods 是通用路由, 是 article 板块的前缀
- 如果使用该路由设置的装饰器那么可以省略的只写 article/first 的内容
- template_folder: 模板文件夹
- 如果想从其他模块的模板文件夹中调度模板来使用, 需要使用 template_folder 来指明模板的搜寻路径
- 同样的, static_folder 与 static_url_path 的功能与 template_folder 类似
- root_path: 根目录的绝对路径, 一般为工程项目的根目录路径
- url_defaults : 默认的路由路径别名, 以字典的形式保存在 Blueprint 类实例中.
- 因为保存的形式是字典, 所以这个参数的值比较特殊, 一定是要含有两个参数的元组形式.
- 例如: url_defaults=(['so','so'])
- 一种参数形式的路由设定方式:
- @customer.route('/<int : any>')
- def do_something(any):
- pass
- 路由参数在客户端输入的值时不确定的, 如上面规定的 int 即整型数 (也可以是 string 类型或者不设定类型). 在定义路由函数的时候, 必须作为形参传入. 那么如果设定了 url_defaluts, 则这个形参的名称就固定了, 不可以为其他. 例如上面的例子: url_defaults=(['so','so']), 那么, 形参就必须为 so, 而不能是 any 了. 显然, blueprint 的这个参数能够有效定义路由的具体功能, 使一个路由更具体化, 避免程序编写过程中随意的改动造成错误.
- 说人话就是 url_defaults 设置以后参数名只能是传入字典的键, 以上面的例子来说如果没有设置 url_defaults 那么参数键值为任意整数均可, 其他情况以此类推.
- 也就是说, 一旦设定了这个参数值, 那么这个路由的别名就定死了.
- '''
关于 route 方法
- @App.route('/','index',index)
- def index():
- pass
- #带引号的是 endpoint, 不带引号的 index 是路由函数名, 必须要与下面定义的函数名相同
- '''
- 关于 endpoint
- endpoint 相当于实际 url 的一个别名, 在浏览器输入地址时, 需要在 flask 后台寻找相应的路由函数 (从而查找相应的资源), 而在查找的过程中, 不是直接用物理地址来进行硬编码的, 而是通过映射成 endpoint 来查找. 也就是说, 开发者定义的每一个路由地址都有一个注册的 endpoint 与之对应. 在客户端输入地址在后台查询资源的时候, 通过这个 endpoint 来查找相应的路由函数.
- '''
深入理解 Flask 请求机制:
所有 Flask 程序都必须创建一个程序实例. Web 服务器把接收来自客户端的所有请求路由都转交给这个实例对象处理. 程序实例是 Flask 类的对象. Flask 类的构造函数只有一个必须指定的参数, 即程序主模块或包的名字, 即我们经常用到的一条语句: App = Flask(name).Python 的 name 变量会存储这些值.
另外, Flask 用蓝图 blueprint 来在一个应用中或跨应用制作应用组件和支持通用的模式. 通过不同的 url_prefix , 从而使用户的请求到达不同模块的 view 函数. 同时, 有效分离了不同模块, 使得开发过程更加的清晰.
App 和蓝图 blueprint 还有许多类方法, 像 route() 方法一样可以作为路由函数的装饰器, 对每一次请求作更精细的判别和操作, 在更高效地进行数据库配置和请求操作, 以及处理错误请求方面有很大的作用.
例如:
- before_first_request #第一次请求的处理
- before_reqeust #注册一个函数来实现对每一个路由请求的拦截
- after_request #每一次请求之后额处理
- app_context #上下文环境
参考链接:
https://blog.csdn.net/qq_35020943/article/details/86919753
来源: http://www.bubuko.com/infodetail-3217251.html