|
|
|
@ -340,7 +340,49 @@ class _ModuleSetupState(object):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Module(_PackageBoundObject): |
|
|
|
|
"""Container object that enables pluggable applications""" |
|
|
|
|
"""Container object that enables pluggable applications. A module can |
|
|
|
|
be used to organize larger applications. They represent blueprints that, |
|
|
|
|
in combination with a :class:`Flask` object are used to create a large |
|
|
|
|
application. |
|
|
|
|
|
|
|
|
|
A module is like an application bound to an `import_name`. Multiple |
|
|
|
|
modules can share the same import names, but in that case a `name` has |
|
|
|
|
to be provided to keep them apart. If different import names are used, |
|
|
|
|
the rightmost part of the import name is used as name. |
|
|
|
|
|
|
|
|
|
Here an example structure for a larger appliation:: |
|
|
|
|
|
|
|
|
|
/myapplication |
|
|
|
|
/__init__.py |
|
|
|
|
/views |
|
|
|
|
/__init__.py |
|
|
|
|
/admin.py |
|
|
|
|
/frontend.py |
|
|
|
|
|
|
|
|
|
The `myapplication/__init__.py` can look like this:: |
|
|
|
|
|
|
|
|
|
from flask import Flask |
|
|
|
|
from myapplication.views.admin import admin |
|
|
|
|
from myapplication.views.frontend import frontend |
|
|
|
|
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
app.register_module(admin, url_prefix='/admin') |
|
|
|
|
app.register_module(frontend) |
|
|
|
|
|
|
|
|
|
And here an example view module (`myapplication/views/admin.py`):: |
|
|
|
|
|
|
|
|
|
from flask import Module |
|
|
|
|
|
|
|
|
|
admin = Module(__name__) |
|
|
|
|
|
|
|
|
|
@admin.route('/') |
|
|
|
|
def index(): |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
@admin.route('/login') |
|
|
|
|
def login(): |
|
|
|
|
pass |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, import_name, name=None, url_prefix=None): |
|
|
|
|
if name is None: |
|
|
|
@ -353,14 +395,18 @@ class Module(_PackageBoundObject):
|
|
|
|
|
self._register_events = [] |
|
|
|
|
|
|
|
|
|
def route(self, rule, **options): |
|
|
|
|
"""Like :meth:`flask.Flask.route` but for a module""" |
|
|
|
|
"""Like :meth:`Flask.route` but for a module. The endpoint for the |
|
|
|
|
:func:`url_for` function is prefixed with the name of the module. |
|
|
|
|
""" |
|
|
|
|
def decorator(f): |
|
|
|
|
self.add_url_rule(rule, f.__name__, f, **options) |
|
|
|
|
return f |
|
|
|
|
return decorator |
|
|
|
|
|
|
|
|
|
def add_url_rule(self, rule, endpoint, view_func=None, **options): |
|
|
|
|
"""Like :meth:`flask.Flask.add_url_rule` but for a module""" |
|
|
|
|
"""Like :meth:`Flask.add_url_rule` but for a module. The endpoint for |
|
|
|
|
the :func:`url_for` function is prefixed with the name of the module. |
|
|
|
|
""" |
|
|
|
|
def register_rule(state): |
|
|
|
|
the_rule = rule |
|
|
|
|
if self.url_prefix: |
|
|
|
@ -370,17 +416,39 @@ class Module(_PackageBoundObject):
|
|
|
|
|
self._record(register_rule) |
|
|
|
|
|
|
|
|
|
def before_request(self, f): |
|
|
|
|
"""Like :meth:`flask.Flask.before_request` but for a module""" |
|
|
|
|
"""Like :meth:`Flask.before_request` but for a module. This function |
|
|
|
|
is only executed before each request that is handled by a function of |
|
|
|
|
that module. |
|
|
|
|
""" |
|
|
|
|
self._record(lambda s: s.app.before_request_funcs |
|
|
|
|
.setdefault(self.name, []).append(f)) |
|
|
|
|
return f |
|
|
|
|
|
|
|
|
|
def before_app_request(self, f): |
|
|
|
|
"""Like :meth:`Flask.before_request`. Such a function is executed |
|
|
|
|
before each request. |
|
|
|
|
""" |
|
|
|
|
self._record(lambda s: s.app.before_request_funcs |
|
|
|
|
.setdefault(None, []).append(f)) |
|
|
|
|
return f |
|
|
|
|
|
|
|
|
|
def after_request(self, f): |
|
|
|
|
"""Like :meth:`flask.Flask.after_request` but for a module""" |
|
|
|
|
"""Like :meth:`Flask.after_request` but for a module. This function |
|
|
|
|
is only executed after each request that is handled by a function of |
|
|
|
|
that module. |
|
|
|
|
""" |
|
|
|
|
self._record(lambda s: s.app.after_request_funcs |
|
|
|
|
.setdefault(self.name, []).append(f)) |
|
|
|
|
return f |
|
|
|
|
|
|
|
|
|
def after_app_request(self, f): |
|
|
|
|
"""Like :meth:`Flask.after_request` but for a module. Such a function |
|
|
|
|
is executed after each request. |
|
|
|
|
""" |
|
|
|
|
self._record(lambda s: s.app.after_request_funcs |
|
|
|
|
.setdefault(None, []).append(f)) |
|
|
|
|
return f |
|
|
|
|
|
|
|
|
|
def _record(self, func): |
|
|
|
|
self._register_events.append(func) |
|
|
|
|
|
|
|
|
@ -594,7 +662,11 @@ class Flask(_PackageBoundObject):
|
|
|
|
|
session.save_cookie(response, self.session_cookie_name) |
|
|
|
|
|
|
|
|
|
def register_module(self, module, **options): |
|
|
|
|
"""Registers a module with this application.""" |
|
|
|
|
"""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: |
|
|
|
|