欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Flask路由与蓝图Blueprint

程序员文章站 2022-09-03 23:50:17
需求分析: 当一个庞大的系统中有很多小模块,在分配路由的时候怎么处理呢?全部都堆到一个py程序中,调用@app.route? 显然这是很不明智的,因为当有几十个模块需要写路由的时候,这样程序员写着写着自己就晕掉了。同时也违背了面向对象设计原则中的控制反转原则。模块与模块之间应该不要太紧密的依赖,高级 ......

需求分析:

当一个庞大的系统中有很多小模块,在分配路由的时候怎么处理呢?全部都堆到一个py程序中,调用@app.route? 显然这是很不明智的,因为当有几十个模块需要写路由的时候,这样程序员写着写着自己就晕掉了。同时也违背了面向对象设计原则中的控制反转原则。模块与模块之间应该不要太紧密的依赖,高级层级模块和低级层级的模块之间的依赖应该有一层抽象来实现。

 

flask框架中,我们可以使用blueprint蓝图来解耦路由分配问题,实现不同业务模块之间的较为松散的依赖。

1. blueprint的实现过程

(1)在子模块views.py文件中定义蓝图

例如:为customer定义一个蓝图路由

customer = blueprint('customer',__name__)

@customer.route()

   def  do_something():

       pass

 

(2)在主模块views.py文件中注册蓝图

app.register_blueprint(customer,url_prefix='/customer')

 

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,其余参数都是选择性的

1. name:即路由的别名,在子模块中定义的蓝图要想通过在主模块中注册使用,就需要定义一个别名

2. import name:表示模块的系统变量,用来区别是子模块还是主模块,这里必须填__name__,表示是在子模块中定义

 

3. url_prefix:路由前缀

例如:想到达http://myblog/article/first

/artile  即是 first前缀

 

4. template_folder:模板文件夹

如果想从其他模块的模板文件夹中调度模板来使用,需要使用template_folder来指明模板的搜寻路径

同样的,static_folder与static_url_path的功能与template_folder类似

 

5. 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的这个参数能够有效定义路由的具体功能,使一个路由更具体化,避免程序编写过程中随意的改动造成错误。

 

也就是说,一旦设定了这个参数值,那么这个路由的别名就定死了。

 

6. root_path:根目录的绝对路径,一般为工程项目的根目录路径

 

 

2. 关于route方法

例子:

@app.route(‘ /’ ,’index’ , index)  

def index():

   pass

#带引号的是endpoint,不带引号的index是路由函数名,必须要与下面定义的函数名相同

 

route()其实是add_url_rule()方法的实例

@app.route(‘ /’ ,’index’,index)

等价于:app.add_url_rule(‘/’,’index’, index)

也可以这样定义endpoint:

app.view_functions[‘index’] = index

 

官方源码:

add_url_rule(rule,endpoint=none,view_func=none,provide_automatic_options=none, **options)

参数解析:

1. rule:在浏览器输入的地址格式

2. view_func:路由函数,即开发者定义的路由

if a view_func is provided it will be registered with the endpoint.

3. endpoint:路由函数的注册别名

 

关于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()方法一样可以作为路由函数的装饰器,对每一次请求作更精细的判别和操作,在更高效地进行数据库配置和请求操作,以及处理错误请求方面有很大的作用。下篇文章我将会写一下这方面的内容。

参考阅读:官方文档http://flask.pocoo.org/docs/dev/api/#flask.flask.add_url_rule

例如:

before_first_request   #第一次请求的处理

before_reqeust       #注册一个函数来实现对每一个路由请求的拦截

after_request        #每一次请求之后额处理

app_context         #上下文环境