diff --git a/docs/blueprints.rst b/docs/blueprints.rst index 7d8ccc56..175ce69f 100644 --- a/docs/blueprints.rst +++ b/docs/blueprints.rst @@ -5,42 +5,51 @@ Modular Applications with Blueprints .. versionadded:: 0.7 -Flask knows a concept known as “blueprints” which can greatly simplify how -large applications work. A blueprint is an object works similar to an -actual :class:`Flask` application object, but it is not actually an -application. Rather it is the blueprint of how to create an application. -Think of it like that: you might want to have an application that has a -wiki. So what you can do is creating the blueprint for a wiki and then -let the application assemble the wiki on the application object. +Flask uses a concept of *blueprints* for making application components and +supporting common patterns within an application or across applications. +Blueprints can greatly simplify how large applications work and provide a +central means for Flask extensions to register operations on applications. +A :class:`Blueprint` object works similarly to a :class:`Flask` +application object, but it is not actually an application. Rather it is a +*blueprint* of how to construct or extend an application. Why Blueprints? --------------- -Why have blueprints and not multiple application objects? The utopia of -pluggable applications are different WSGI applications and merging them -together somehow. You can do that (see :ref:`app-dispatch`) but it's not -the right tool for every case. Having different applications means having -different configs. Applications are also separated on the WSGI layer -which is a lot lower level than the level that Flask usually operates on -where you have request and response objects. +Blueprints in Flask are intended for these cases: -Blueprints do not necessarily have to implement applications. They could -only provide filters for templates, static files, templates or similar -things. They share the same config as the application and can change the -application as necessary when being registered. +* Factor an application into a set of blueprints. This is ideal for + larger applications; a project could instantiate an application object, + initialize several extensions, and register a collection of blueprints. +* Register a blueprint on an application at a URL prefix and/or subdomain. + Paremeters in the URL prefix/subdomain become common view arguments + (with defaults) across all view functions in the blueprint. +* Register a blueprint multiple times on an application with different URL + rules. +* Provide template filters, static files, templates, and other utilities + through blueprints. A blueprint does not have to implement applications + or view functions. +* Register a blueprint on an application for any of these cases when + initializing a Flask extension. -The downside is that you cannot unregister a blueprint once application -without having to destroy the whole application object. +A blueprint in Flask is not a pluggable app because it is not actually an +application -- it's a set of operations which can be registered on an +application, even multiple times. Why not have multiple application +objects? You can do that (see :ref:`app-dispatch`), but your applications +will have separate configs and will be managed at the WSGI layer. + +Blueprints instead provide separation at the Flask level, share +application config, and can change an application object as necessary with +being registered. The downside is that you cannot unregister a blueprint +once application without having to destroy the whole application object. The Concept of Blueprints ------------------------- -The basic concept of blueprints is that they record operations that should -be executed when the blueprint is registered on the application. However -additionally each time a request gets dispatched to a view that was -declared to a blueprint Flask will remember that the request was -dispatched to that blueprint. That way it's easier to generate URLs from -one endpoint to another in the same module. +The basic concept of blueprints is that they record operations to execute +when registered on an application. Flask associates view functions with +blueprints when dispatching requests and generating URLs from one endpoint +to another. My First Blueprint ------------------ diff --git a/docs/reqcontext.rst b/docs/reqcontext.rst index 088502eb..832f0e66 100644 --- a/docs/reqcontext.rst +++ b/docs/reqcontext.rst @@ -174,13 +174,14 @@ It's easy to see the behavior from the command line: >>> app = Flask(__name__) >>> @app.teardown_request -... def after_request(exception=None): -... print 'after request' -... +... def teardown_request(exception=None): +... print 'this runs after request' +... >>> ctx = app.test_request_context() >>> ctx.push() >>> ctx.pop() -after request +this runs after request +>>> .. _notes-on-proxies: diff --git a/flask/blueprints.py b/flask/blueprints.py index 2c45248a..181f0c16 100644 --- a/flask/blueprints.py +++ b/flask/blueprints.py @@ -124,8 +124,8 @@ class Blueprint(_PackageBoundObject): deferred(state) def route(self, rule, **options): - """Like :meth:`Flask.route` but for a module. The endpoint for the - :func:`url_for` function is prefixed with the name of the module. + """Like :meth:`Flask.route` but for a blueprint. The endpoint for the + :func:`url_for` function is prefixed with the name of the blueprint. """ def decorator(f): self.add_url_rule(rule, f.__name__, f, **options) @@ -133,15 +133,15 @@ class Blueprint(_PackageBoundObject): return decorator def add_url_rule(self, rule, endpoint=None, view_func=None, **options): - """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. + """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for + the :func:`url_for` function is prefixed with the name of the blueprint. """ 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 - prefix the endpoint with the module name, this has to be done + """Like :meth:`Flask.endpoint` but for a blueprint. This does not + prefix the endpoint with the blueprint name, this has to be done explicitly by the user of this method. If the endpoint is prefixed with a `.` it will be registered to the current blueprint, otherwise it's an application independent endpoint. @@ -154,9 +154,9 @@ class Blueprint(_PackageBoundObject): return decorator def before_request(self, f): - """Like :meth:`Flask.before_request` but for a module. This function + """Like :meth:`Flask.before_request` but for a blueprint. This function is only executed before each request that is handled by a function of - that module. + that blueprint. """ self.record_once(lambda s: s.app.before_request_funcs .setdefault(self.name, []).append(f)) @@ -164,48 +164,48 @@ class Blueprint(_PackageBoundObject): def before_app_request(self, f): """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 blueprint. """ self.record_once(lambda s: s.app.before_request_funcs .setdefault(None, []).append(f)) return f def after_request(self, f): - """Like :meth:`Flask.after_request` but for a module. This function + """Like :meth:`Flask.after_request` but for a blueprint. This function is only executed after each request that is handled by a function of - that module. + that blueprint. """ self.record_once(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, even if outside of the module. + """Like :meth:`Flask.after_request` but for a blueprint. Such a function + is executed after each request, even if outside of the blueprint. """ self.record_once(lambda s: s.app.after_request_funcs .setdefault(None, []).append(f)) return f def context_processor(self, f): - """Like :meth:`Flask.context_processor` but for a module. This - function is only executed for requests handled by a module. + """Like :meth:`Flask.context_processor` but for a blueprint. This + function is only executed for requests handled by a blueprint. """ self.record_once(lambda s: s.app.template_context_processors .setdefault(self.name, []).append(f)) return f def app_context_processor(self, f): - """Like :meth:`Flask.context_processor` but for a module. Such a - function is executed each request, even if outside of the module. + """Like :meth:`Flask.context_processor` but for a blueprint. Such a + function is executed each request, even if outside of the blueprint. """ self.record_once(lambda s: s.app.template_context_processors .setdefault(None, []).append(f)) return f def app_errorhandler(self, code): - """Like :meth:`Flask.errorhandler` but for a module. This - handler is used for all requests, even if outside of the module. + """Like :meth:`Flask.errorhandler` but for a blueprint. This + handler is used for all requests, even if outside of the blueprint. """ def decorator(f): self.record_once(lambda s: s.app.errorhandler(code)(f)) @@ -222,7 +222,7 @@ class Blueprint(_PackageBoundObject): return f def url_defaults(self, f): - """Callback function for URL defaults for this module. It's called + """Callback function for URL defaults for this blueprint. It's called with the endpoint and values and should update the values passed in place. """