专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python爱好者社区  ·  英伟达憾失DeepSeek关键人才?美国放走 ... ·  昨天  
Python爱好者社区  ·  离谱!下载DeepSeek最高判刑20年? ·  2 天前  
Python爱好者社区  ·  1885页的Python完全版电子书 ·  3 天前  
Python开发者  ·  o3-mini 碾压 DeepSeek ... ·  5 天前  
Python开发者  ·  请立即拿下软考证书(政策风口) ·  4 天前  
51好读  ›  专栏  ›  Python开发者

Flask 中模块化应用的实现

Python开发者  · 公众号  · Python  · 2017-10-09 20:00

正文

(点击 上方蓝字 ,快速关注我们)


来源:fanchunke1991

fanchunke.me/Flask/Flask中模块化应用的实现/

如有好文章投稿,请点击 → 这里了解详情


Flask是一个轻量级的Web框架。虽然是轻量级的,但是对于组件一个大型的、模块化应用也是能够实现的,“蓝图”就是这样一种实现。对于模块化应用的实现,在Flask 0.2版本中进行了设计。本文暂时不对“蓝图”做详细的介绍,而是先从0.2版本中的Module类的实现讲起。其实,“蓝图”的实现和Module类的实现很相似。


为什么实现模块化应用


对于大型应用而言,随着功能的不断增加,整个应用的规模也会扩大。按照一定的规则将应用的不同部分进行模块化,不仅能够使整个应用逻辑清晰,也易于维护。例如,在Flask中,你也许想像如下构建一个简单的项目:


/ myapplication

/ __init__ . py

/ views

/ __init__ . py

/ admin . py

/ frontend . py


以上目录结构中,我们将之前的Flask单文件修改成了一个应用包,所有的视图函数都在views下,并且按照功能分为了admin和frontend两个部分。为了实现这种模块化应用的构建,在0.2版本中Flask实现了Module类。这个类实例可以通过注册的方式,在Flask应用创建后添加进应用。


Module类实现了一系列的方法:


  • route(rule, **options)

  • add_url_rule(rule, endpoint, view_func=None, **options)

  • before_request(f)

  • before_app_request(f)

  • after_request(f)

  • after_app_request(f)

  • context_processor(f)

  • app_context_processor(f)

  • _record(func)


以上方法除了add_url_rule和_record外,都可以作为装饰器在自己的模块中使用,这些装饰器都返回一个函数。通过调用_record方法,可以将装饰器返回的函数放到_register_events中。当Flask应用创建之后,通过运行_register_events列表中的函数,可以将这个模块注册到应用中去。


Flask应用怎么注册一个Module


以下我们以一个例子来说明Flask应用怎么注册一个Module。


1. 项目结构


这个简单的例子项目结构如下:


/ myapplication

/ __init__ . py

/ app . py

/ views

/ __init__ . py

/ admin . py

/ blog . py


admin.py和blog.py两个模块的代码如下:


# admin.py

from flask import Module


admin = Module ( __name__ )


@ admin . route ( '/' )

def index () :

return "This is admin page!"


@ admin . route ( '/profile' )

def profile () :

return "This is profile page."


# blog.py

from flask import Module

blog = Module ( __name__ )

@ blog . route ( '/' )

def index () :

return "This is my blog!"

@ blog . route ( '/article/ ' )

def article ( id ) :

return "The article id is %d." % id


以上两个模块中,我们首先分别创建了一个Module类,然后像写一般的视图函数一样,为每个模块增加一些规则。之后,可以在创建Flask应用的时候将这些模块引入,就可以注册了。


# app.py

from flask import Flask

from views . admin import admin

from views . blog import blog

app = Flask ( __name__ )

@ app . route ( '/' )

def index () :

return "This is my app."

app . register_module ( blog , url_prefix = '/blog' )

app . register_module ( admin , url_prefix = '/admin' )

if __name__ == '__main__' :

from werkzeug . serving import run_simple

run_simple ( 'localhost' , 5000 , app )


在app.py中:


  • 我们首先引入了admin和blog两个Module对象;

  • 之后,我们创建了一个Flask应用app,并且为这个应用增加了一个视图函数;

  • 为了注册模块,我们调用了应用的register_module方法;

  • 最后,从werkzeug.serving中我们调用run_simple方法,用来创建一个本地的服务器用于测试这个Flask应用。


根据以上的步骤,我们就可以测试这个应用。分别以/blog和/admin为URL前缀,就可以访问blog和admin两个模块了。


2. 注册Module时发生了什么


根据上面的例子,只要简单的调用Flask应用的register_module方法,就可以注册一个Module了。关于register_module方法的代码如下:


def register_module ( self , module , ** options ) :

"""Registers a module with this application.  The keyword argument

of this function are the same as the ones for the constructor of the

:class:`Module` class and will override the values of the module if

provided.

"""

options . setdefault ( 'url_prefix' , module . url_prefix )

state = _ModuleSetupState ( self , ** options )

for func in module . _register_events :

func ( state )


通过以上代码可以发现:


  • 可以通过增加url_prefix来区分不同的Module,这在app注册admin和blog时我们已经看到了;

  • 在注册时,我们创建了一个_ModuleSetupState的类,这个类接收Flask应用和一些参数生成一个state实例。这个实例反映了当前Flask应用的状态。

  • 前面在讲到Module类的时候,我们讲到Module未注册时会将自己模块的一些功能实现都放在_register_events列表中,这些功能实现都是函数形式。当需要将模块注册到某一应用上时,只需要传递关于这个应用信息的参数即可,即就是上面的state实例。这样,通过运行函数,可以讲一些属性绑定到当前应用上去。


以上面例子中不同模块的URL绑定来讲,通过注册,应用app现形成了如下的URL“地图”:


>>> app . url_map

Map ([ < Rule '/admin/profile' ( HEAD , GET ) -> admin . profile > ,

< Rule '/admin/' ( HEAD , GET ) -> admin . index > ,

< Rule '/blog/' ( HEAD , GET ) -> blog . index > ,

< Rule '/' ( HEAD , GET ) -> index > ,

< Rule '/blog/article/ ' ( HEAD , GET ) -> blog . article > ,

< Rule '/static/ ' ( HEAD , GET ) -> static > ]

)

>>> app . url_map . _rules_by _ endpoint

{ 'admin.index' : [ < Rule '/admin/' ( HEAD , GET ) -> admin . index > ],

'admin.profile' : [ < Rule '/admin/profile' ( HEAD , GET







请到「今天看啥」查看全文