Browse Source

Register most stuff only once

pull/262/head
Armin Ronacher 14 years ago
parent
commit
f7e71b518f
  1. 4
      flask/app.py
  2. 39
      flask/blueprints.py

4
flask/app.py

@ -583,6 +583,7 @@ class Flask(_PackageBoundObject):
.. versionadded:: 0.7
"""
first_registration = False
if blueprint.name in self.blueprints:
assert self.blueprints[blueprint.name] is blueprint, \
'A blueprint\'s name collision ocurred between %r and ' \
@ -590,7 +591,8 @@ class Flask(_PackageBoundObject):
(blueprint, self.blueprints[blueprint.name], blueprint.name)
else:
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):
"""Connects a URL rule. Works exactly like the :meth:`route`

39
flask/blueprints.py

@ -10,6 +10,7 @@
:license: BSD, see LICENSE for more details.
"""
import os
from functools import update_wrapper
from .helpers import _PackageBoundObject, _endpoint_from_view_func
@ -19,10 +20,11 @@ class BlueprintSetupState(object):
application.
"""
def __init__(self, blueprint, app, options):
def __init__(self, blueprint, app, options, first_registration):
self.app = app
self.blueprint = blueprint
self.options = options
self.first_registration = first_registration
subdomain = self.options.get('subdomain')
if subdomain is None:
@ -64,17 +66,23 @@ class Blueprint(_PackageBoundObject):
def _record(self, func):
self.deferred_functions.append(func)
def make_setup_state(self, app, options):
return BlueprintSetupState(self, app, options)
def _record_once(self, func):
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
on the application. This can be overridden to customize the register
behavior. Keyword arguments from
:func:`~flask.Flask.register_blueprint` are directly forwarded to this
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:
state.add_url_rule(self.static_url_path + '/<path:filename>',
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
the :func:`url_for` function is prefixed with the name of the module.
"""
def register_rule(state):
state.add_url_rule(rule, endpoint, view_func, **options)
self._record(register_rule)
self._record(lambda s:
s.add_url_rule(rule, endpoint, view_func, **options))
def endpoint(self, endpoint):
"""Like :meth:`Flask.endpoint` but for a module. This does not
@ -108,7 +115,7 @@ class Blueprint(_PackageBoundObject):
def decorator(f):
def register_endpoint(state):
state.app.view_functions[endpoint] = f
self._record(register_endpoint)
self._record_once(register_endpoint)
return f
return decorator
@ -117,7 +124,7 @@ class Blueprint(_PackageBoundObject):
is only executed before each request that is handled by a function of
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))
return f
@ -125,7 +132,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.before_request`. Such a function is executed
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))
return f
@ -134,7 +141,7 @@ class Blueprint(_PackageBoundObject):
is only executed after each request that is handled by a function of
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))
return f
@ -142,7 +149,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.after_request` but for a module. Such a function
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))
return f
@ -150,7 +157,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.context_processor` but for a module. This
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))
return f
@ -158,7 +165,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.context_processor` but for a module. Such a
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))
return f
@ -167,6 +174,6 @@ class Blueprint(_PackageBoundObject):
handler is used for all requests, even if outside of the module.
"""
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 decorator

Loading…
Cancel
Save