2019独角兽企业重金招聘Python工程师标准>>>
作为微框架,即便只有一个文件也可以编写基于 Flask 的 Web 应用。然而对于许多现实世界中的应用,拥有数十个以上的视图(view)是非常正常的,这时候,Flask 建议使用多个 Python 模块来组织视图。例如:
/ yourapplication / yourapplication / __init__.py / views __init__.py admin.py frontend.py / static / style.css / templates layout.html index.html login.html ... |
视图保存在包yourapplication.views中。这里只需要放置一个空白的__init__.py文件即可。我们来看看包中的admin.py文件。首先,我们使用 Python 模块名称创建一个 Flask 模块(flask.Module)对象,这个对象行为上非常类似 flask.Flask 对象,它们大多数方法都是一样的。下面是一个易于理解的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from flask import Module admin = Module(__name__) @admin .route( '/' ) def index(): pass @admin .route( '/login' ) def login(): pass @admin .route( '/logout' ) def logout(): pass |
对于frontend.py我们也可以做类似的处理,接下来,我们只需要确保在整个应用程序的__init__.py中注册这些模块即可:
1 2 3 4 5 6 7 | from flask import Flask from yourapplication.views.admin import admin from yourapplication.views.frontend import frontend app = Flask(__name__) app.register_module(admin, url_prefix = '/admin' ) app.register_module(frontend) |
通过将这些模块注册到应用中,应用程序的 URL 映射表就能够适用于这些模块中的配置了。请注意 admin 模块的注册参数 url_prefix:默认的当我们注册一个模块时,缺省的 endpoint 是“/”,要使用其它的前缀,必须通过 url_prefix 参数配置。
使用 Flask 模块和直接使用 Flask 对象有什么区别呢?最主要的区别在 URL 生成的问题上。例如,我们经常使用的 url_for() 函数,当直接与 Flask 对象一起工作时,它的第一个参数,也就是所谓的 endpoint,是视图函数的名称,而当结合 Flask 模块一起工作时,对于同一个模块中的视图函数,用法仍然一样,而对于别的模块中的函数,则需要使用模块名加上句点作为前缀。看看下面的例子可以帮助我们更 容易的理解这个问题。假设我们在 admin 模块中有一个需要重定向到 frontend 模块的函数,它看起来类似这样:
1 2 3 4 5 6 7 | @admin .route( '/to_frontend' ) def to_frontend(): return redirect(url_for( 'frontend.index' )) @frontend .route( '/' ) def index(): return "I'm the frontend index" |
而如果我们只需要重定向到相同模块中的其它函数,那么我们既可以使用完成的 endpoint 路径,也可以只使用函数名:
1 2 3 4 5 6 7 | @frontend .route( '/to_index' ) def to_index(): return redirect(url_for( 'index' )) @frontend .route( '/' ) def index(): return "I'm the index" |
更进一步,如果我们的 Module 对象是放在 Python 包中的,这样,我们有增加了额外的放置模板和静态文件的位置。假设我们的应用程序看起来像是这样的:
/ yourapplication __init__.py / apps __init__.py / frontend __init__.py views.py / static style.css / templates index.html about.html ... / admin __init__.py views.py / static style.css / templates list_items.html show_item.html ... |
这些包中的静态目录将会被自动展开为 URL。假设这个admin模块是通过 /admin 前缀展现在 URL 中的,那么可以通过/admin/static/style.css 来访问其中的样式表文件。而该文件的 endpoint 则是 'admin.static'。
与 URL 规则可以省略前缀不同,我们总是需要使用完成的模块名称来引用模板,例如:render_template('admin/list_items.html') 等等。同样的,既然我们的视图函数已经从yourapplication.views.admin移动到yourapplication.apps.admin.views中了,我们需要在注册模块的时候明确的设置一个名称。这是由于再使用 __name__ 作为参数的话它这时候的值是 views 了:
1 2 | # in yourapplication/apps/admin/views.py admin = Module(__name__, 'admin' ) |
同样的,引导程序也需要稍作调整:
1 2 3 4 5 6 7 8 | # in yourapplication/__init__.py from flask import Flask from yourapplication.apps.admin.views import admin from yourapplication.apps.frontend.views import frontend app = Flask(__name__) app.register_module(admin, url_prefix = '/admin' ) app.register_module(frontend) |
值得注意的是,如果我们使用一个不合格的 endpoint,默认的 Flask 会将它当作是模块的静态文件目录,即便这个目录并不存在。这对于任何 endpoint 都有效,而不仅仅是名为 static 的目录,只不过通常我们使用 static 放置静态文件而非设置一个视图函数而已。如果需要使用整个应用程序的静态目录,可以在最开始加上一个句点:
1 2 3 4 5 | # this refers to the application's static folder url_for( '.static' , filename = 'static.css' ) # this refers to the current module's static folder url_for( 'static' , filename = 'static.css' ) |