| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  |     flask | 
					
						
							|  |  |  |     ~~~~~ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     A microframework based on Werkzeug.  It's extensively documented | 
					
						
							|  |  |  |     and follows best practice patterns. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     :copyright: (c) 2010 by Armin Ronacher. | 
					
						
							|  |  |  |     :license: BSD, see LICENSE for more details. | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2010-04-14 23:08:38 +08:00
										 |  |  | from __future__ import with_statement | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | from jinja2 import Environment, PackageLoader, FileSystemLoader | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  | from werkzeug import Request as RequestBase, Response as ResponseBase, \ | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  |      LocalStack, LocalProxy, create_environ, SharedDataMiddleware, \ | 
					
						
							| 
									
										
										
										
											2010-04-20 05:49:02 +08:00
										 |  |  |      ImmutableDict, cached_property | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | from werkzeug.routing import Map, Rule | 
					
						
							| 
									
										
										
										
											2010-04-19 05:37:03 +08:00
										 |  |  | from werkzeug.exceptions import HTTPException | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | from werkzeug.contrib.securecookie import SecureCookie | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | # try to load the best simplejson implementation available.  If JSON | 
					
						
							|  |  |  | # is not installed, we add a failing class. | 
					
						
							|  |  |  | json_available = True | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import simplejson as json | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         import json | 
					
						
							|  |  |  |     except ImportError: | 
					
						
							|  |  |  |         json_available = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | # utilities we import from Werkzeug and Jinja2 that are unused | 
					
						
							|  |  |  | # in the module but are exported as public interface. | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  | from werkzeug import abort, redirect | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | from jinja2 import Markup, escape | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  | # use pkg_resource if that works, otherwise fall back to cwd.  The | 
					
						
							|  |  |  | # current working directory is generally not reliable with the notable | 
					
						
							|  |  |  | # exception of google appengine. | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import pkg_resources | 
					
						
							|  |  |  |     pkg_resources.resource_stream | 
					
						
							|  |  |  | except (ImportError, AttributeError): | 
					
						
							|  |  |  |     pkg_resources = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  | class Request(RequestBase): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """The request object used by default in flask.  Remembers the
 | 
					
						
							|  |  |  |     matched endpoint and view arguments. | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     It is what ends up as :class:`~flask.request`.  If you want to replace | 
					
						
							|  |  |  |     the request object used you can subclass this and set | 
					
						
							|  |  |  |     :attr:`~flask.Flask.request_class` to your subclass. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, environ): | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |         RequestBase.__init__(self, environ) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.endpoint = None | 
					
						
							|  |  |  |         self.view_args = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  |     @cached_property | 
					
						
							|  |  |  |     def json(self): | 
					
						
							|  |  |  |         """If the mimetype is `application/json` this will contain the
 | 
					
						
							|  |  |  |         parsed JSON data. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if not json_available: | 
					
						
							|  |  |  |             raise AttributeError('simplejson not available') | 
					
						
							|  |  |  |         if self.mimetype == 'application/json': | 
					
						
							|  |  |  |             return json.loads(self.data) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  | class Response(ResponseBase): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """The response object that is used by default in flask.  Works like the
 | 
					
						
							|  |  |  |     response object from Werkzeug but is set to have a HTML mimetype by | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |     default.  Quite often you don't have to create this object yourself because | 
					
						
							|  |  |  |     :meth:`~flask.Flask.make_response` will take care of that for you. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If you want to replace the response object used you can subclass this and | 
					
						
							|  |  |  |     set :attr:`~flask.Flask.request_class` to your subclass. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     default_mimetype = 'text/html' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _RequestGlobals(object): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-17 20:10:47 +08:00
										 |  |  | class _NullSession(SecureCookie): | 
					
						
							|  |  |  |     """Class used to generate nicer error messages if sessions are not
 | 
					
						
							|  |  |  |     available.  Will still allow read-only access to the empty session | 
					
						
							|  |  |  |     but fail on setting. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _fail(self, *args, **kwargs): | 
					
						
							|  |  |  |         raise RuntimeError('the session is unavailable because no secret ' | 
					
						
							|  |  |  |                            'key was set.  Set the secret_key on the ' | 
					
						
							|  |  |  |                            'application to something unique and secret') | 
					
						
							|  |  |  |     __setitem__ = __delitem__ = clear = pop = popitem = \ | 
					
						
							|  |  |  |         update = setdefault = _fail | 
					
						
							|  |  |  |     del _fail | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | class _RequestContext(object): | 
					
						
							|  |  |  |     """The request context contains all request relevant information.  It is
 | 
					
						
							|  |  |  |     created at the beginning of the request and pushed to the | 
					
						
							|  |  |  |     `_request_ctx_stack` and removed at the end of it.  It will create the | 
					
						
							|  |  |  |     URL adapter and request object for the WSGI environment provided. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, app, environ): | 
					
						
							|  |  |  |         self.app = app | 
					
						
							|  |  |  |         self.url_adapter = app.url_map.bind_to_environ(environ) | 
					
						
							|  |  |  |         self.request = app.request_class(environ) | 
					
						
							|  |  |  |         self.session = app.open_session(self.request) | 
					
						
							| 
									
										
										
										
											2010-04-17 20:10:47 +08:00
										 |  |  |         if self.session is None: | 
					
						
							|  |  |  |             self.session = _NullSession() | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.g = _RequestGlobals() | 
					
						
							|  |  |  |         self.flashes = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-16 08:27:37 +08:00
										 |  |  |     def __enter__(self): | 
					
						
							|  |  |  |         _request_ctx_stack.push(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __exit__(self, exc_type, exc_value, tb): | 
					
						
							|  |  |  |         # do not pop the request stack if we are in debug mode and an | 
					
						
							|  |  |  |         # exception happened.  This will allow the debugger to still | 
					
						
							|  |  |  |         # access the request object in the interactive shell. | 
					
						
							|  |  |  |         if tb is None or not self.app.debug: | 
					
						
							|  |  |  |             _request_ctx_stack.pop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | def url_for(endpoint, **values): | 
					
						
							|  |  |  |     """Generates a URL to the given endpoint with the method provided.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     :param endpoint: the endpoint of the URL (name of the function) | 
					
						
							|  |  |  |     :param values: the variable arguments of the URL rule | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return _request_ctx_stack.top.url_adapter.build(endpoint, values) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-18 21:44:06 +08:00
										 |  |  | def get_template_attribute(template_name, attribute): | 
					
						
							|  |  |  |     """Loads a macro (or variable) a template exports.  This can be used to
 | 
					
						
							|  |  |  |     invoke a macro from within Python code.  If you for example have a | 
					
						
							|  |  |  |     template named `_foo.html` with the following contents: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .. sourcecode:: html+jinja | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        {% macro hello(name) %}Hello {{ name }}!{% endmacro %} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     You can access this from Python code like this:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hello = get_template_attribute('_foo.html', 'hello') | 
					
						
							|  |  |  |         return hello('World') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  |     .. versionadded:: 0.2 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-18 21:44:06 +08:00
										 |  |  |     :param template_name: the name of the template | 
					
						
							|  |  |  |     :param attribute: the name of the variable of macro to acccess | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return getattr(current_app.jinja_env.get_template(template_name).module, | 
					
						
							|  |  |  |                    attribute) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | def flash(message): | 
					
						
							|  |  |  |     """Flashes a message to the next request.  In order to remove the
 | 
					
						
							|  |  |  |     flashed message from the session and to display it to the user, | 
					
						
							|  |  |  |     the template has to call :func:`get_flashed_messages`. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param message: the message to be flashed. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     session['_flashes'] = (session.get('_flashes', [])) + [message] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_flashed_messages(): | 
					
						
							|  |  |  |     """Pulls all flashed messages from the session and returns them.
 | 
					
						
							|  |  |  |     Further calls in the same request to the function will return | 
					
						
							|  |  |  |     the same messages. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     flashes = _request_ctx_stack.top.flashes | 
					
						
							|  |  |  |     if flashes is None: | 
					
						
							|  |  |  |         _request_ctx_stack.top.flashes = flashes = \ | 
					
						
							|  |  |  |             session.pop('_flashes', []) | 
					
						
							|  |  |  |     return flashes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | def jsonify(*args, **kwargs): | 
					
						
							|  |  |  |     """Creates a :class:`~flask.Response` with the JSON representation of
 | 
					
						
							|  |  |  |     the given arguments with an `application/json` mimetype.  The arguments | 
					
						
							|  |  |  |     to this function are the same as to the :class:`dict` constructor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example usage:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @app.route('/_get_current_user') | 
					
						
							|  |  |  |         def get_current_user(): | 
					
						
							|  |  |  |             return jsonify(username=g.user.username, | 
					
						
							|  |  |  |                            email=g.user.email, | 
					
						
							|  |  |  |                            id=g.user.id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This will send a JSON response like this to the browser:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "username": "admin", | 
					
						
							|  |  |  |             "email": "admin@localhost", | 
					
						
							|  |  |  |             "id": 42 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This requires Python 2.6 or an installed version of simplejson. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .. versionadded:: 0.2 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return current_app.response_class(json.dumps(dict(*args, **kwargs), | 
					
						
							|  |  |  |         indent=None if request.is_xhr else 2), mimetype='application/json') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | def render_template(template_name, **context): | 
					
						
							|  |  |  |     """Renders a template from the template folder with the given
 | 
					
						
							|  |  |  |     context. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param template_name: the name of the template to be rendered | 
					
						
							|  |  |  |     :param context: the variables that should be available in the | 
					
						
							|  |  |  |                     context of the template. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |     current_app.update_template_context(context) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     return current_app.jinja_env.get_template(template_name).render(context) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def render_template_string(source, **context): | 
					
						
							|  |  |  |     """Renders a template from the given template source string
 | 
					
						
							|  |  |  |     with the given context. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param template_name: the sourcecode of the template to be | 
					
						
							|  |  |  |                           rendered | 
					
						
							|  |  |  |     :param context: the variables that should be available in the | 
					
						
							|  |  |  |                     context of the template. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |     current_app.update_template_context(context) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     return current_app.jinja_env.from_string(source).render(context) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 01:52:18 +08:00
										 |  |  | def _default_template_ctx_processor(): | 
					
						
							|  |  |  |     """Default template context processor.  Injects `request`,
 | 
					
						
							|  |  |  |     `session` and `g`. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     reqctx = _request_ctx_stack.top | 
					
						
							|  |  |  |     return dict( | 
					
						
							|  |  |  |         request=reqctx.request, | 
					
						
							|  |  |  |         session=reqctx.session, | 
					
						
							|  |  |  |         g=reqctx.g | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-16 08:14:54 +08:00
										 |  |  | def _get_package_path(name): | 
					
						
							|  |  |  |     """Returns the path to a package or cwd if that cannot be found.""" | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         return os.path.abspath(os.path.dirname(sys.modules[name].__file__)) | 
					
						
							|  |  |  |     except (KeyError, AttributeError): | 
					
						
							|  |  |  |         return os.getcwd() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-20 00:51:04 +08:00
										 |  |  | def _tojson_filter(string, *args, **kwargs): | 
					
						
							|  |  |  |     """Calls dumps for the template engine, escaping Slashes properly.""" | 
					
						
							| 
									
										
										
										
											2010-04-20 05:54:38 +08:00
										 |  |  |     return json.dumps(string, *args, **kwargs).replace('</', '<\\/') | 
					
						
							| 
									
										
										
										
											2010-04-20 00:51:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | class Flask(object): | 
					
						
							|  |  |  |     """The flask object implements a WSGI application and acts as the central
 | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |     object.  It is passed the name of the module or package of the | 
					
						
							|  |  |  |     application.  Once it is created it will act as a central registry for | 
					
						
							|  |  |  |     the view functions, the URL rules, template configuration and much more. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The name of the package is used to resolve resources from inside the | 
					
						
							|  |  |  |     package or the folder the module is contained in depending on if the | 
					
						
							|  |  |  |     package parameter resolves to an actual python package (a folder with | 
					
						
							|  |  |  |     an `__init__.py` file inside) or a standard module (just a `.py` file). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For more information about resource loading, see :func:`open_resource`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Usually you create a :class:`Flask` instance in your main module or | 
					
						
							|  |  |  |     in the `__init__.py` file of your package like this:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from flask import Flask | 
					
						
							|  |  |  |         app = Flask(__name__) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |     #: the class that is used for request objects.  See :class:`~flask.request` | 
					
						
							|  |  |  |     #: for more information. | 
					
						
							|  |  |  |     request_class = Request | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |     #: the class that is used for response objects.  See | 
					
						
							|  |  |  |     #: :class:`~flask.Response` for more information. | 
					
						
							|  |  |  |     response_class = Response | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #: path for the static files.  If you don't want to use static files | 
					
						
							|  |  |  |     #: you can set this value to `None` in which case no URL rule is added | 
					
						
							|  |  |  |     #: and the development server will no longer serve any static files. | 
					
						
							|  |  |  |     static_path = '/static' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #: if a secret key is set, cryptographic components can use this to | 
					
						
							|  |  |  |     #: sign cookies and other things.  Set this to a complex random value | 
					
						
							|  |  |  |     #: when you want to use the secure cookie for instance. | 
					
						
							|  |  |  |     secret_key = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #: The secure cookie uses this for the name of the session cookie | 
					
						
							|  |  |  |     session_cookie_name = 'session' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #: options that are passed directly to the Jinja2 environment | 
					
						
							| 
									
										
										
										
											2010-04-20 05:49:02 +08:00
										 |  |  |     jinja_options = ImmutableDict( | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         autoescape=True, | 
					
						
							|  |  |  |         extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, package_name): | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         #: the debug flag.  Set this to `True` to enable debugging of | 
					
						
							|  |  |  |         #: the application.  In debug mode the debugger will kick in | 
					
						
							|  |  |  |         #: when an unhandled exception ocurrs and the integrated server | 
					
						
							|  |  |  |         #: will automatically reload the application if changes in the | 
					
						
							|  |  |  |         #: code are detected. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.debug = False | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: the name of the package or module.  Do not change this once | 
					
						
							|  |  |  |         #: it was set by the constructor. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.package_name = package_name | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  |         #: where is the app root located? | 
					
						
							| 
									
										
										
										
											2010-04-16 08:14:54 +08:00
										 |  |  |         self.root_path = _get_package_path(self.package_name) | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         #: a dictionary of all view functions registered.  The keys will | 
					
						
							|  |  |  |         #: be function names which are also used to generate URLs and | 
					
						
							|  |  |  |         #: the values are the function objects themselves. | 
					
						
							|  |  |  |         #: to register a view function, use the :meth:`route` decorator. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.view_functions = {} | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: a dictionary of all registered error handlers.  The key is | 
					
						
							|  |  |  |         #: be the error code as integer, the value the function that | 
					
						
							|  |  |  |         #: should handle that error. | 
					
						
							|  |  |  |         #: To register a error handler, use the :meth:`errorhandler` | 
					
						
							|  |  |  |         #: decorator. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.error_handlers = {} | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: a list of functions that should be called at the beginning | 
					
						
							|  |  |  |         #: of the request before request dispatching kicks in.  This | 
					
						
							|  |  |  |         #: can for example be used to open database connections or | 
					
						
							|  |  |  |         #: getting hold of the currently logged in user. | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         #: To register a function here, use the :meth:`before_request` | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         #: decorator. | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         self.before_request_funcs = [] | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: a list of functions that are called at the end of the | 
					
						
							|  |  |  |         #: request.  Tha function is passed the current response | 
					
						
							|  |  |  |         #: object and modify it in place or replace it. | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         #: To register a function here use the :meth:`after_request` | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         #: decorator. | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         self.after_request_funcs = [] | 
					
						
							| 
									
										
										
										
											2010-04-13 01:52:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: a list of functions that are called without arguments | 
					
						
							|  |  |  |         #: to populate the template context.  Each returns a dictionary | 
					
						
							|  |  |  |         #: that the template context is updated with. | 
					
						
							|  |  |  |         #: To register a function here, use the :meth:`context_processor` | 
					
						
							|  |  |  |         #: decorator. | 
					
						
							|  |  |  |         self.template_context_processors = [_default_template_ctx_processor] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-20 05:49:02 +08:00
										 |  |  |         #: the :class:`~werkzeug.routing.Map` for this instance.  You can use | 
					
						
							|  |  |  |         #: this to change the routing converters after the class was created | 
					
						
							|  |  |  |         #: but before any routes are connected.  Example:: | 
					
						
							|  |  |  |         #: | 
					
						
							|  |  |  |         #:    from werkzeug import BaseConverter | 
					
						
							|  |  |  |         #: | 
					
						
							|  |  |  |         #:    class ListConverter(BaseConverter): | 
					
						
							|  |  |  |         #:        def to_python(self, value): | 
					
						
							|  |  |  |         #:            return value.split(',') | 
					
						
							|  |  |  |         #:        def to_url(self, values): | 
					
						
							|  |  |  |         #:            return ','.join(BaseConverter.to_url(value) | 
					
						
							|  |  |  |         #:                            for value in values) | 
					
						
							|  |  |  |         #: | 
					
						
							|  |  |  |         #:    app = Flask(__name__) | 
					
						
							|  |  |  |         #:    app.url_map.converters['list'] = ListConverter | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.url_map = Map() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.static_path is not None: | 
					
						
							| 
									
										
										
										
											2010-04-20 05:49:02 +08:00
										 |  |  |             self.add_url_rule(self.static_path + '/<filename>', | 
					
						
							|  |  |  |                               build_only=True, endpoint='static') | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  |             if pkg_resources is not None: | 
					
						
							|  |  |  |                 target = (self.package_name, 'static') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 target = os.path.join(self.root_path, 'static') | 
					
						
							| 
									
										
										
										
											2010-04-14 20:11:00 +08:00
										 |  |  |             self.wsgi_app = SharedDataMiddleware(self.wsgi_app, { | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  |                 self.static_path: target | 
					
						
							| 
									
										
										
										
											2010-04-14 20:11:00 +08:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         #: the Jinja2 environment.  It is created from the | 
					
						
							|  |  |  |         #: :attr:`jinja_options` and the loader that is returned | 
					
						
							|  |  |  |         #: by the :meth:`create_jinja_loader` function. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         self.jinja_env = Environment(loader=self.create_jinja_loader(), | 
					
						
							|  |  |  |                                      **self.jinja_options) | 
					
						
							|  |  |  |         self.jinja_env.globals.update( | 
					
						
							|  |  |  |             url_for=url_for, | 
					
						
							|  |  |  |             get_flashed_messages=get_flashed_messages | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  |         if json_available: | 
					
						
							| 
									
										
										
										
											2010-04-20 00:51:04 +08:00
										 |  |  |             self.jinja_env.filters['tojson'] = _tojson_filter | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def create_jinja_loader(self): | 
					
						
							|  |  |  |         """Creates the Jinja loader.  By default just a package loader for
 | 
					
						
							|  |  |  |         the configured package is returned that looks up templates in the | 
					
						
							|  |  |  |         `templates` folder.  To add other loaders it's possible to | 
					
						
							|  |  |  |         override this method. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  |         if pkg_resources is None: | 
					
						
							|  |  |  |             return FileSystemLoader(os.path.join(self.root_path, 'templates')) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         return PackageLoader(self.package_name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |     def update_template_context(self, context): | 
					
						
							|  |  |  |         """Update the template context with some commonly used variables.
 | 
					
						
							|  |  |  |         This injects request, session and g into the template context. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param context: the context as a dictionary that is updated in place | 
					
						
							|  |  |  |                         to add extra variables. | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-13 01:52:18 +08:00
										 |  |  |         for func in self.template_context_processors: | 
					
						
							|  |  |  |             context.update(func()) | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     def run(self, host='localhost', port=5000, **options): | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """Runs the application on a local development server.  If the
 | 
					
						
							|  |  |  |         :attr:`debug` flag is set the server will automatically reload | 
					
						
							|  |  |  |         for code changes and show a debugger in case an exception happened. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param host: the hostname to listen on.  set this to ``'0.0.0.0'`` | 
					
						
							|  |  |  |                      to have the server available externally as well. | 
					
						
							|  |  |  |         :param port: the port of the webserver | 
					
						
							|  |  |  |         :param options: the options to be forwarded to the underlying | 
					
						
							|  |  |  |                         Werkzeug server.  See :func:`werkzeug.run_simple` | 
					
						
							|  |  |  |                         for more information. | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         from werkzeug import run_simple | 
					
						
							|  |  |  |         if 'debug' in options: | 
					
						
							|  |  |  |             self.debug = options.pop('debug') | 
					
						
							|  |  |  |         options.setdefault('use_reloader', self.debug) | 
					
						
							|  |  |  |         options.setdefault('use_debugger', self.debug) | 
					
						
							|  |  |  |         return run_simple(host, port, self, **options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 00:45:06 +08:00
										 |  |  |     def test_client(self): | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |         """Creates a test client for this application.  For information
 | 
					
						
							|  |  |  |         about unit testing head over to :ref:`testing`. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         from werkzeug import Client | 
					
						
							|  |  |  |         return Client(self, self.response_class, use_cookies=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def open_resource(self, resource): | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """Opens a resource from the application's resource folder.  To see
 | 
					
						
							|  |  |  |         how this works, consider the following folder structure:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /myapplication.py | 
					
						
							|  |  |  |             /schemal.sql | 
					
						
							|  |  |  |             /static | 
					
						
							|  |  |  |                 /style.css | 
					
						
							|  |  |  |             /template | 
					
						
							|  |  |  |                 /layout.html | 
					
						
							|  |  |  |                 /index.html | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If you want to open the `schema.sql` file you would do the | 
					
						
							|  |  |  |         following:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with app.open_resource('schema.sql') as f: | 
					
						
							|  |  |  |                 contents = f.read() | 
					
						
							|  |  |  |                 do_something_with(contents) | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param resource: the name of the resource.  To access resources within | 
					
						
							|  |  |  |                          subfolders use forward slashes as separator. | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-14 21:16:38 +08:00
										 |  |  |         if pkg_resources is None: | 
					
						
							|  |  |  |             return open(os.path.join(self.root_path, resource), 'rb') | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         return pkg_resources.resource_stream(self.package_name, resource) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def open_session(self, request): | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """Creates or opens a new session.  Default implementation stores all
 | 
					
						
							|  |  |  |         session data in a signed cookie.  This requires that the | 
					
						
							|  |  |  |         :attr:`secret_key` is set. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param request: an instance of :attr:`request_class`. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         key = self.secret_key | 
					
						
							|  |  |  |         if key is not None: | 
					
						
							|  |  |  |             return SecureCookie.load_cookie(request, self.session_cookie_name, | 
					
						
							|  |  |  |                                             secret_key=key) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def save_session(self, session, response): | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """Saves the session if it needs updates.  For the default
 | 
					
						
							|  |  |  |         implementation, check :meth:`open_session`. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param session: the session to be saved (a | 
					
						
							|  |  |  |                         :class:`~werkzeug.contrib.securecookie.SecureCookie` | 
					
						
							|  |  |  |                         object) | 
					
						
							| 
									
										
										
										
											2010-04-13 01:52:18 +08:00
										 |  |  |         :param response: an instance of :attr:`response_class` | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-17 20:10:47 +08:00
										 |  |  |         session.save_cookie(response, self.session_cookie_name) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-20 00:29:56 +08:00
										 |  |  |     def add_url_rule(self, rule, endpoint, view_func=None, **options): | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  |         """Connects a URL rule.  Works exactly like the :meth:`route`
 | 
					
						
							| 
									
										
										
										
											2010-04-20 00:29:56 +08:00
										 |  |  |         decorator. If a view_func is provided it will be registered with the endpoint. | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Basically this example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/') | 
					
						
							|  |  |  |             def index(): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-10 21:49:15 +08:00
										 |  |  |         Is equivalent to the following:: | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             def index(): | 
					
						
							|  |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2010-04-20 00:29:56 +08:00
										 |  |  |             app.add_url_rule('/', 'index', index) | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |          If the view_func is not provided you will need to connect the endpoint to a  | 
					
						
							|  |  |  |          view function like so: | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  |             app.view_functions['index'] = index | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param rule: the URL rule as string | 
					
						
							|  |  |  |         :param endpoint: the endpoint for the registered URL rule.  Flask | 
					
						
							|  |  |  |                          itself assumes the name of the view function as | 
					
						
							|  |  |  |                          endpoint | 
					
						
							| 
									
										
										
										
											2010-04-20 00:29:56 +08:00
										 |  |  |         :param view_func: the function to call when servicing a request to the provided endpoint | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  |         :param options: the options to be forwarded to the underlying | 
					
						
							|  |  |  |                         :class:`~werkzeug.routing.Rule` object | 
					
						
							| 
									
										
										
										
											2010-04-20 01:11:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         .. versionadded:: 0.2 | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-10 21:49:15 +08:00
										 |  |  |         options['endpoint'] = endpoint | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  |         options.setdefault('methods', ('GET',)) | 
					
						
							|  |  |  |         self.url_map.add(Rule(rule, **options)) | 
					
						
							| 
									
										
										
										
											2010-04-20 00:29:56 +08:00
										 |  |  |         if view_func is not None: | 
					
						
							|  |  |  |             self.view_functions[endpoint] = view_func | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     def route(self, rule, **options): | 
					
						
							|  |  |  |         """A decorator that is used to register a view function for a
 | 
					
						
							|  |  |  |         given URL rule.  Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/') | 
					
						
							|  |  |  |             def index(): | 
					
						
							|  |  |  |                 return 'Hello World' | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Variables parts in the route can be specified with angular | 
					
						
							|  |  |  |         brackets (``/user/<username>``).  By default a variable part | 
					
						
							| 
									
										
										
										
											2010-04-12 01:18:40 +08:00
										 |  |  |         in the URL accepts any string without a slash however a different | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         converter can be specified as well by using ``<converter:name>``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Variable parts are passed to the view function as keyword | 
					
						
							|  |  |  |         arguments. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The following converters are possible: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         =========== =========================================== | 
					
						
							|  |  |  |         `int`       accepts integers | 
					
						
							|  |  |  |         `float`     like `int` but for floating point values | 
					
						
							|  |  |  |         `path`      like the default but also accepts slashes | 
					
						
							|  |  |  |         =========== =========================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Here some examples:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/') | 
					
						
							|  |  |  |             def index(): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/<username>') | 
					
						
							|  |  |  |             def show_user(username): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/post/<int:post_id>') | 
					
						
							|  |  |  |             def show_post(post_id): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 07:32:39 +08:00
										 |  |  |         An important detail to keep in mind is how Flask deals with trailing | 
					
						
							|  |  |  |         slashes.  The idea is to keep each URL unique so the following rules | 
					
						
							|  |  |  |         apply: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         1. If a rule ends with a slash and is requested without a slash | 
					
						
							|  |  |  |            by the user, the user is automatically redirected to the same | 
					
						
							|  |  |  |            page with a trailing slash attached. | 
					
						
							|  |  |  |         2. If a rule does not end with a trailing slash and the user request | 
					
						
							|  |  |  |            the page with a trailing slash, a 404 not found is raised. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This is consistent with how web servers deal with static files.  This | 
					
						
							|  |  |  |         also makes it possible to use relative link targets safely. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         The :meth:`route` decorator accepts a couple of other arguments | 
					
						
							|  |  |  |         as well: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  |         :param rule: the URL rule as string | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         :param methods: a list of methods this rule should be limited | 
					
						
							| 
									
										
										
										
											2010-04-09 07:32:39 +08:00
										 |  |  |                         to (``GET``, ``POST`` etc.).  By default a rule | 
					
						
							|  |  |  |                         just listens for ``GET`` (and implicitly ``HEAD``). | 
					
						
							| 
									
										
										
										
											2010-04-06 22:02:14 +08:00
										 |  |  |         :param subdomain: specifies the rule for the subdoain in case | 
					
						
							|  |  |  |                           subdomain matching is in use. | 
					
						
							|  |  |  |         :param strict_slashes: can be used to disable the strict slashes | 
					
						
							|  |  |  |                                setting for this rule.  See above. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  |         :param options: other options to be forwarded to the underlying | 
					
						
							|  |  |  |                         :class:`~werkzeug.routing.Rule` object. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         def decorator(f): | 
					
						
							| 
									
										
										
										
											2010-04-20 01:11:58 +08:00
										 |  |  |             self.add_url_rule(rule, f.__name__, f, **options) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |             return f | 
					
						
							|  |  |  |         return decorator | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def errorhandler(self, code): | 
					
						
							|  |  |  |         """A decorator that is used to register a function give a given
 | 
					
						
							|  |  |  |         error code.  Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.errorhandler(404) | 
					
						
							|  |  |  |             def page_not_found(): | 
					
						
							|  |  |  |                 return 'This page does not exist', 404 | 
					
						
							| 
									
										
										
										
											2010-04-09 19:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         You can also register a function as error handler without using | 
					
						
							|  |  |  |         the :meth:`errorhandler` decorator.  The following example is | 
					
						
							|  |  |  |         equivalent to the one above:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def page_not_found(): | 
					
						
							|  |  |  |                 return 'This page does not exist', 404 | 
					
						
							|  |  |  |             app.error_handlers[404] = page_not_found | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param code: the code as integer for the handler | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         def decorator(f): | 
					
						
							|  |  |  |             self.error_handlers[code] = f | 
					
						
							|  |  |  |             return f | 
					
						
							|  |  |  |         return decorator | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |     def before_request(self, f): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """Registers a function to run before each request.""" | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         self.before_request_funcs.append(f) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         return f | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |     def after_request(self, f): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """Register a function to be run after each request.""" | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         self.after_request_funcs.append(f) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         return f | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 01:52:18 +08:00
										 |  |  |     def context_processor(self, f): | 
					
						
							|  |  |  |         """Registers a template context processor function.""" | 
					
						
							|  |  |  |         self.template_context_processors.append(f) | 
					
						
							|  |  |  |         return f | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     def match_request(self): | 
					
						
							|  |  |  |         """Matches the current request against the URL map and also
 | 
					
						
							|  |  |  |         stores the endpoint and view arguments on the request object | 
					
						
							|  |  |  |         is successful, otherwise the exception is stored. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         rv = _request_ctx_stack.top.url_adapter.match() | 
					
						
							|  |  |  |         request.endpoint, request.view_args = rv | 
					
						
							|  |  |  |         return rv | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def dispatch_request(self): | 
					
						
							|  |  |  |         """Does the request dispatching.  Matches the URL and returns the
 | 
					
						
							|  |  |  |         return value of the view or error handler.  This does not have to | 
					
						
							|  |  |  |         be a response object.  In order to convert the return value to a | 
					
						
							|  |  |  |         proper response object, call :func:`make_response`. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             endpoint, values = self.match_request() | 
					
						
							|  |  |  |             return self.view_functions[endpoint](**values) | 
					
						
							|  |  |  |         except HTTPException, e: | 
					
						
							|  |  |  |             handler = self.error_handlers.get(e.code) | 
					
						
							|  |  |  |             if handler is None: | 
					
						
							|  |  |  |                 return e | 
					
						
							|  |  |  |             return handler(e) | 
					
						
							|  |  |  |         except Exception, e: | 
					
						
							|  |  |  |             handler = self.error_handlers.get(500) | 
					
						
							|  |  |  |             if self.debug or handler is None: | 
					
						
							|  |  |  |                 raise | 
					
						
							|  |  |  |             return handler(e) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_response(self, rv): | 
					
						
							|  |  |  |         """Converts the return value from a view function to a real
 | 
					
						
							|  |  |  |         response object that is an instance of :attr:`response_class`. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         The following types are allowd for `rv`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ======================= =========================================== | 
					
						
							|  |  |  |         :attr:`response_class`  the object is returned unchanged | 
					
						
							|  |  |  |         :class:`str`            a response object is created with the | 
					
						
							|  |  |  |                                 string as body | 
					
						
							|  |  |  |         :class:`unicode`        a response object is created with the | 
					
						
							|  |  |  |                                 string encoded to utf-8 as body | 
					
						
							|  |  |  |         :class:`tuple`          the response object is created with the | 
					
						
							|  |  |  |                                 contents of the tuple as arguments | 
					
						
							|  |  |  |         a WSGI function         the function is called as WSGI application | 
					
						
							|  |  |  |                                 and buffered as response object | 
					
						
							|  |  |  |         ======================= =========================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param rv: the return value from the view function | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         if isinstance(rv, self.response_class): | 
					
						
							|  |  |  |             return rv | 
					
						
							|  |  |  |         if isinstance(rv, basestring): | 
					
						
							|  |  |  |             return self.response_class(rv) | 
					
						
							|  |  |  |         if isinstance(rv, tuple): | 
					
						
							|  |  |  |             return self.response_class(*rv) | 
					
						
							|  |  |  |         return self.response_class.force_type(rv, request.environ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def preprocess_request(self): | 
					
						
							|  |  |  |         """Called before the actual request dispatching and will
 | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         call every as :meth:`before_request` decorated function. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         If any of these function returns a value it's handled as | 
					
						
							|  |  |  |         if it was the return value from the view and further | 
					
						
							|  |  |  |         request handling is stopped. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         for func in self.before_request_funcs: | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |             rv = func() | 
					
						
							|  |  |  |             if rv is not None: | 
					
						
							|  |  |  |                 return rv | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def process_response(self, response): | 
					
						
							|  |  |  |         """Can be overridden in order to modify the response object
 | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         before it's sent to the WSGI server.  By default this will | 
					
						
							|  |  |  |         call all the :meth:`after_request` decorated functions. | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :param response: a :attr:`response_class` object. | 
					
						
							|  |  |  |         :return: a new response object or the same, has to be an | 
					
						
							|  |  |  |                  instance of :attr:`response_class`. | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         session = _request_ctx_stack.top.session | 
					
						
							| 
									
										
										
										
											2010-04-17 20:10:47 +08:00
										 |  |  |         if not isinstance(session, _NullSession): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |             self.save_session(session, response) | 
					
						
							| 
									
										
										
										
											2010-04-16 17:03:16 +08:00
										 |  |  |         for handler in self.after_request_funcs: | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |             response = handler(response) | 
					
						
							|  |  |  |         return response | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def wsgi_app(self, environ, start_response): | 
					
						
							|  |  |  |         """The actual WSGI application.  This is not implemented in
 | 
					
						
							| 
									
										
										
										
											2010-04-18 21:44:06 +08:00
										 |  |  |         `__call__` so that middlewares can be applied without losing a | 
					
						
							|  |  |  |         reference to the class.  So instead of doing this:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             app = MyMiddleware(app) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         It's a better idea to do this instead:: | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             app.wsgi_app = MyMiddleware(app.wsgi_app) | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-18 21:44:06 +08:00
										 |  |  |         Then you still have the original application object around and | 
					
						
							|  |  |  |         can continue to call methods on it. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  |         :param environ: a WSGI environment | 
					
						
							|  |  |  |         :param start_response: a callable accepting a status code, | 
					
						
							|  |  |  |                                a list of headers and an optional | 
					
						
							|  |  |  |                                exception context to start the response | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |         with self.request_context(environ): | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |             rv = self.preprocess_request() | 
					
						
							|  |  |  |             if rv is None: | 
					
						
							|  |  |  |                 rv = self.dispatch_request() | 
					
						
							|  |  |  |             response = self.make_response(rv) | 
					
						
							|  |  |  |             response = self.process_response(response) | 
					
						
							|  |  |  |             return response(environ, start_response) | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def request_context(self, environ): | 
					
						
							|  |  |  |         """Creates a request context from the given environment and binds
 | 
					
						
							|  |  |  |         it to the current context.  This must be used in combination with | 
					
						
							|  |  |  |         the `with` statement because the request is only bound to the | 
					
						
							|  |  |  |         current context for the duration of the `with` block. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Example usage:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with app.request_context(environ): | 
					
						
							|  |  |  |                 do_something_with(request) | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         :params environ: a WSGI environment | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-04-16 08:27:37 +08:00
										 |  |  |         return _RequestContext(self, environ) | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |     def test_request_context(self, *args, **kwargs): | 
					
						
							|  |  |  |         """Creates a WSGI environment from the given values (see
 | 
					
						
							| 
									
										
										
										
											2010-04-11 08:20:10 +08:00
										 |  |  |         :func:`werkzeug.create_environ` for more information, this | 
					
						
							|  |  |  |         function accepts the same arguments). | 
					
						
							| 
									
										
										
										
											2010-04-09 01:03:15 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         return self.request_context(create_environ(*args, **kwargs)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 19:12:57 +08:00
										 |  |  |     def __call__(self, environ, start_response): | 
					
						
							|  |  |  |         """Shortcut for :attr:`wsgi_app`""" | 
					
						
							|  |  |  |         return self.wsgi_app(environ, start_response) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # context locals | 
					
						
							|  |  |  | _request_ctx_stack = LocalStack() | 
					
						
							|  |  |  | current_app = LocalProxy(lambda: _request_ctx_stack.top.app) | 
					
						
							|  |  |  | request = LocalProxy(lambda: _request_ctx_stack.top.request) | 
					
						
							|  |  |  | session = LocalProxy(lambda: _request_ctx_stack.top.session) | 
					
						
							|  |  |  | g = LocalProxy(lambda: _request_ctx_stack.top.g) |