Register most stuff only once
This commit is contained in:
parent
7a08331ac0
commit
f7e71b518f
2 changed files with 26 additions and 17 deletions
|
|
@ -583,6 +583,7 @@ class Flask(_PackageBoundObject):
|
||||||
|
|
||||||
.. versionadded:: 0.7
|
.. versionadded:: 0.7
|
||||||
"""
|
"""
|
||||||
|
first_registration = False
|
||||||
if blueprint.name in self.blueprints:
|
if blueprint.name in self.blueprints:
|
||||||
assert self.blueprints[blueprint.name] is blueprint, \
|
assert self.blueprints[blueprint.name] is blueprint, \
|
||||||
'A blueprint\'s name collision ocurred between %r and ' \
|
'A blueprint\'s name collision ocurred between %r and ' \
|
||||||
|
|
@ -590,7 +591,8 @@ class Flask(_PackageBoundObject):
|
||||||
(blueprint, self.blueprints[blueprint.name], blueprint.name)
|
(blueprint, self.blueprints[blueprint.name], blueprint.name)
|
||||||
else:
|
else:
|
||||||
self.blueprints[blueprint.name] = blueprint
|
self.blueprints[blueprint.name] = blueprint
|
||||||
blueprint.register(self, options)
|
first_registration = True
|
||||||
|
blueprint.register(self, options, first_registration)
|
||||||
|
|
||||||
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
|
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
|
||||||
"""Connects a URL rule. Works exactly like the :meth:`route`
|
"""Connects a URL rule. Works exactly like the :meth:`route`
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
from functools import update_wrapper
|
||||||
|
|
||||||
from .helpers import _PackageBoundObject, _endpoint_from_view_func
|
from .helpers import _PackageBoundObject, _endpoint_from_view_func
|
||||||
|
|
||||||
|
|
@ -19,10 +20,11 @@ class BlueprintSetupState(object):
|
||||||
application.
|
application.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, blueprint, app, options):
|
def __init__(self, blueprint, app, options, first_registration):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.blueprint = blueprint
|
self.blueprint = blueprint
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self.first_registration = first_registration
|
||||||
|
|
||||||
subdomain = self.options.get('subdomain')
|
subdomain = self.options.get('subdomain')
|
||||||
if subdomain is None:
|
if subdomain is None:
|
||||||
|
|
@ -64,17 +66,23 @@ class Blueprint(_PackageBoundObject):
|
||||||
def _record(self, func):
|
def _record(self, func):
|
||||||
self.deferred_functions.append(func)
|
self.deferred_functions.append(func)
|
||||||
|
|
||||||
def make_setup_state(self, app, options):
|
def _record_once(self, func):
|
||||||
return BlueprintSetupState(self, app, options)
|
def wrapper(state):
|
||||||
|
if state.first_registration:
|
||||||
|
func(state)
|
||||||
|
return self._record(update_wrapper(wrapper, func))
|
||||||
|
|
||||||
def register(self, app, options):
|
def make_setup_state(self, app, options, first_registration=False):
|
||||||
|
return BlueprintSetupState(self, app, options, first_registration)
|
||||||
|
|
||||||
|
def register(self, app, options, first_registration=False):
|
||||||
"""Called by :meth:`Flask.register_blueprint` to register a blueprint
|
"""Called by :meth:`Flask.register_blueprint` to register a blueprint
|
||||||
on the application. This can be overridden to customize the register
|
on the application. This can be overridden to customize the register
|
||||||
behavior. Keyword arguments from
|
behavior. Keyword arguments from
|
||||||
:func:`~flask.Flask.register_blueprint` are directly forwarded to this
|
:func:`~flask.Flask.register_blueprint` are directly forwarded to this
|
||||||
method in the `options` dictionary.
|
method in the `options` dictionary.
|
||||||
"""
|
"""
|
||||||
state = self.make_setup_state(app, options)
|
state = self.make_setup_state(app, options, first_registration)
|
||||||
if self.has_static_folder:
|
if self.has_static_folder:
|
||||||
state.add_url_rule(self.static_url_path + '/<path:filename>',
|
state.add_url_rule(self.static_url_path + '/<path:filename>',
|
||||||
view_func=self.send_static_file,
|
view_func=self.send_static_file,
|
||||||
|
|
@ -96,9 +104,8 @@ class Blueprint(_PackageBoundObject):
|
||||||
"""Like :meth:`Flask.add_url_rule` but for a module. The endpoint for
|
"""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.
|
the :func:`url_for` function is prefixed with the name of the module.
|
||||||
"""
|
"""
|
||||||
def register_rule(state):
|
self._record(lambda s:
|
||||||
state.add_url_rule(rule, endpoint, view_func, **options)
|
s.add_url_rule(rule, endpoint, view_func, **options))
|
||||||
self._record(register_rule)
|
|
||||||
|
|
||||||
def endpoint(self, endpoint):
|
def endpoint(self, endpoint):
|
||||||
"""Like :meth:`Flask.endpoint` but for a module. This does not
|
"""Like :meth:`Flask.endpoint` but for a module. This does not
|
||||||
|
|
@ -108,7 +115,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
def register_endpoint(state):
|
def register_endpoint(state):
|
||||||
state.app.view_functions[endpoint] = f
|
state.app.view_functions[endpoint] = f
|
||||||
self._record(register_endpoint)
|
self._record_once(register_endpoint)
|
||||||
return f
|
return f
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
@ -117,7 +124,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
is only executed before each request that is handled by a function of
|
is only executed before each request that is handled by a function of
|
||||||
that module.
|
that module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.before_request_funcs
|
self._record_once(lambda s: s.app.before_request_funcs
|
||||||
.setdefault(self.name, []).append(f))
|
.setdefault(self.name, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -125,7 +132,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
"""Like :meth:`Flask.before_request`. Such a function is executed
|
"""Like :meth:`Flask.before_request`. Such a function is executed
|
||||||
before each request, even if outside of a module.
|
before each request, even if outside of a module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.before_request_funcs
|
self._record_once(lambda s: s.app.before_request_funcs
|
||||||
.setdefault(None, []).append(f))
|
.setdefault(None, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -134,7 +141,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
is only executed after each request that is handled by a function of
|
is only executed after each request that is handled by a function of
|
||||||
that module.
|
that module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.after_request_funcs
|
self._record_once(lambda s: s.app.after_request_funcs
|
||||||
.setdefault(self.name, []).append(f))
|
.setdefault(self.name, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -142,7 +149,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
"""Like :meth:`Flask.after_request` but for a module. Such a function
|
"""Like :meth:`Flask.after_request` but for a module. Such a function
|
||||||
is executed after each request, even if outside of the module.
|
is executed after each request, even if outside of the module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.after_request_funcs
|
self._record_once(lambda s: s.app.after_request_funcs
|
||||||
.setdefault(None, []).append(f))
|
.setdefault(None, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -150,7 +157,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
"""Like :meth:`Flask.context_processor` but for a module. This
|
"""Like :meth:`Flask.context_processor` but for a module. This
|
||||||
function is only executed for requests handled by a module.
|
function is only executed for requests handled by a module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.template_context_processors
|
self._record_once(lambda s: s.app.template_context_processors
|
||||||
.setdefault(self.name, []).append(f))
|
.setdefault(self.name, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -158,7 +165,7 @@ class Blueprint(_PackageBoundObject):
|
||||||
"""Like :meth:`Flask.context_processor` but for a module. Such a
|
"""Like :meth:`Flask.context_processor` but for a module. Such a
|
||||||
function is executed each request, even if outside of the module.
|
function is executed each request, even if outside of the module.
|
||||||
"""
|
"""
|
||||||
self._record(lambda s: s.app.template_context_processors
|
self._record_once(lambda s: s.app.template_context_processors
|
||||||
.setdefault(None, []).append(f))
|
.setdefault(None, []).append(f))
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
@ -167,6 +174,6 @@ class Blueprint(_PackageBoundObject):
|
||||||
handler is used for all requests, even if outside of the module.
|
handler is used for all requests, even if outside of the module.
|
||||||
"""
|
"""
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
self._record(lambda s: s.app.errorhandler(code)(f))
|
self._record_once(lambda s: s.app.errorhandler(code)(f))
|
||||||
return f
|
return f
|
||||||
return decorator
|
return decorator
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue