# -*- coding: utf-8 -*-"""flask.blueprints~~~~~~~~~~~~~~~~Blueprints are the recommended way to implement larger or morepluggable applications in Flask 0.7 and later.:copyright: © 2010 by the Pallets team.:license: BSD, see LICENSE for more details."""from functools import update_wrapperfrom werkzeug.urls import url_joinfrom .helpers import _PackageBoundObject, _endpoint_from_view_funcclass BlueprintSetupState(object):"""Temporary holder object for registering a blueprint with theapplication. An instance of this class is created by the:meth:`~flask.Blueprint.make_setup_state` method and later passedto all register callback functions."""def __init__(self, blueprint, app, options, first_registration):#: a reference to the current applicationself.app = app#: a reference to the blueprint that created this setup state.self.blueprint = blueprint#: a dictionary with all options that were passed to the#: :meth:`~flask.Flask.register_blueprint` method.self.options = options#: as blueprints can be registered multiple times with the#: application and not everything wants to be registered#: multiple times on it, this attribute can be used to figure#: out if the blueprint was registered in the past already.self.first_registration = first_registrationsubdomain = self.options.get('subdomain')if subdomain is None:subdomain = self.blueprint.subdomain#: The subdomain that the blueprint should be active for, ``None``#: otherwise.self.subdomain = subdomainurl_prefix = self.options.get('url_prefix')if url_prefix is None:url_prefix = self.blueprint.url_prefix#: The prefix that should be used for all URLs defined on the#: blueprint.self.url_prefix = url_prefix#: A dictionary with URL defaults that is added to each and every#: URL that was defined with the blueprint.self.url_defaults = dict(self.blueprint.url_values_defaults)self.url_defaults.update(self.options.get('url_defaults', ()))def add_url_rule(self, rule, endpoint=None, view_func=None, **options):"""A helper method to register a rule (and optionally a view function)to the application. The endpoint is automatically prefixed with theblueprint's name."""if self.url_prefix is not None:if rule:rule = '/'.join((self.url_prefix.rstrip('/'), rule.lstrip('/')))else:rule = self.url_prefixoptions.setdefault('subdomain', self.subdomain)if endpoint is None:endpoint = _endpoint_from_view_func(view_func)defaults = self.url_defaultsif 'defaults' in options:defaults = dict(defaults, **options.pop('defaults'))self.app.add_url_rule(rule, '%s.%s' % (self.blueprint.name, endpoint),view_func, defaults=defaults, **options)class Blueprint(_PackageBoundObject):"""Represents a blueprint. A blueprint is an object that recordsfunctions that will be called with the:class:`~flask.blueprints.BlueprintSetupState` later to register functionsor other things on the main application. See :ref:`blueprints` for moreinformation... versionadded:: 0.7"""warn_on_modifications = False_got_registered_once = False#: Blueprint local JSON decoder class to use.#: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_encoder`.json_encoder = None#: Blueprint local JSON decoder class to use.#: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_decoder`.json_decoder = None# TODO remove the next three attrs when Sphinx :inherited-members: works# https://github.com/sphinx-doc/sphinx/issues/741#: The name of the package or module that this app belongs to. Do not#: change this once it is set by the constructor.import_name = None#: Location of the template files to be added to the template lookup.#: ``None`` if templates should not be added.template_folder = None#: Absolute path to the package on the filesystem. Used to look up#: resources contained in the package.root_path = Nonedef __init__(self, name, import_name, static_folder=None,static_url_path=None, template_folder=None,url_prefix=None, subdomain=None, url_defaults=None,root_path=None):_PackageBoundObject.__init__(self, import_name, template_folder,root_path=root_path)self.name = nameself.url_prefix = url_prefixself.subdomain = subdomainself.static_folder = static_folderself.static_url_path = static_url_pathself.deferred_functions = []if url_defaults is None:url_defaults = {}self.url_values_defaults = url_defaultsdef record(self, func):"""Registers a function that is called when the blueprint isregistered on the application. This function is called with thestate as argument as returned by the :meth:`make_setup_state`method."""if self._got_registered_once and self.warn_on_modifications:from warnings import warnwarn(Warning('The blueprint was already registered once ''but is getting modified now. These changes ''will not show up.'))self.deferred_functions.append(func)def record_once(self, func):"""Works like :meth:`record` but wraps the function in anotherfunction that will ensure the function is only called once. If theblueprint is registered a second time on the application, thefunction passed is not called."""def wrapper(state):if state.first_registration:func(state)return self.record(update_wrapper(wrapper, func))def make_setup_state(self, app, options, first_registration=False):"""Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState`object that is later passed to the register callback functions.Subclasses can override this to return a subclass of the setup state."""return BlueprintSetupState(self, app, options, first_registration)def register(self, app, options, first_registration=False):"""Called by :meth:`Flask.register_blueprint` to register all viewsand callbacks registered on the blueprint with the application. Createsa :class:`.BlueprintSetupState` and calls each :meth:`record` callbackwith it.:param app: The application this blueprint is being registered with.:param options: Keyword arguments forwarded from:meth:`~Flask.register_blueprint`.:param first_registration: Whether this is the first time thisblueprint has been registered on the application."""self._got_registered_once = Truestate = 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, endpoint='static')for deferred in self.deferred_functions:deferred(state)def route(self, rule, **options):"""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):endpoint = options.pop("endpoint", f.__name__)self.add_url_rule(rule, endpoint, f, **options)return freturn decoratordef add_url_rule(self, rule, endpoint=None, view_func=None, **options):"""Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint forthe :func:`url_for` function is prefixed with the name of the blueprint."""if endpoint:assert '.' not in endpoint, "Blueprint endpoints should not contain dots"if view_func and hasattr(view_func, '__name__'):assert '.' not in view_func.__name__, "Blueprint view function name should not contain dots"self.record(lambda s:s.add_url_rule(rule, endpoint, view_func, **options))def endpoint(self, endpoint):"""Like :meth:`Flask.endpoint` but for a blueprint. This does notprefix the endpoint with the blueprint name, this has to be doneexplicitly by the user of this method. If the endpoint is prefixedwith a `.` it will be registered to the current blueprint, otherwiseit's an application independent endpoint."""def decorator(f):def register_endpoint(state):state.app.view_functions[endpoint] = fself.record_once(register_endpoint)return freturn decoratordef app_template_filter(self, name=None):"""Register a custom template filter, available application wide. Like:meth:`Flask.template_filter` but for a blueprint.:param name: the optional name of the filter, otherwise thefunction name will be used."""def decorator(f):self.add_app_template_filter(f, name=name)return freturn decoratordef add_app_template_filter(self, f, name=None):"""Register a custom template filter, available application wide. Like:meth:`Flask.add_template_filter` but for a blueprint. Works exactlylike the :meth:`app_template_filter` decorator.:param name: the optional name of the filter, otherwise thefunction name will be used."""def register_template(state):state.app.jinja_env.filters[name or f.__name__] = fself.record_once(register_template)def app_template_test(self, name=None):"""Register a custom template test, available application wide. Like:meth:`Flask.template_test` but for a blueprint... versionadded:: 0.10:param name: the optional name of the test, otherwise thefunction name will be used."""def decorator(f):self.add_app_template_test(f, name=name)return freturn decoratordef add_app_template_test(self, f, name=None):"""Register a custom template test, available application wide. Like:meth:`Flask.add_template_test` but for a blueprint. Works exactlylike the :meth:`app_template_test` decorator... versionadded:: 0.10:param name: the optional name of the test, otherwise thefunction name will be used."""def register_template(state):state.app.jinja_env.tests[name or f.__name__] = fself.record_once(register_template)def app_template_global(self, name=None):"""Register a custom template global, available application wide. Like:meth:`Flask.template_global` but for a blueprint... versionadded:: 0.10:param name: the optional name of the global, otherwise thefunction name will be used."""def decorator(f):self.add_app_template_global(f, name=name)return freturn decoratordef add_app_template_global(self, f, name=None):"""Register a custom template global, available application wide. Like:meth:`Flask.add_template_global` but for a blueprint. Works exactlylike the :meth:`app_template_global` decorator... versionadded:: 0.10:param name: the optional name of the global, otherwise thefunction name will be used."""def register_template(state):state.app.jinja_env.globals[name or f.__name__] = fself.record_once(register_template)def before_request(self, f):"""Like :meth:`Flask.before_request` but for a blueprint. This functionis only executed before each request that is handled by a function ofthat blueprint."""self.record_once(lambda s: s.app.before_request_funcs.setdefault(self.name, []).append(f))return fdef before_app_request(self, f):"""Like :meth:`Flask.before_request`. Such a function is executedbefore each request, even if outside of a blueprint."""self.record_once(lambda s: s.app.before_request_funcs.setdefault(None, []).append(f))return fdef before_app_first_request(self, f):"""Like :meth:`Flask.before_first_request`. Such a function isexecuted before the first request to the application."""self.record_once(lambda s: s.app.before_first_request_funcs.append(f))return fdef after_request(self, f):"""Like :meth:`Flask.after_request` but for a blueprint. This functionis only executed after each request that is handled by a function ofthat blueprint."""self.record_once(lambda s: s.app.after_request_funcs.setdefault(self.name, []).append(f))return fdef after_app_request(self, f):"""Like :meth:`Flask.after_request` but for a blueprint. Such a functionis 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 fdef teardown_request(self, f):"""Like :meth:`Flask.teardown_request` but for a blueprint. Thisfunction is only executed when tearing down requests handled by afunction of that blueprint. Teardown request functions are executedwhen the request context is popped, even when no actual request wasperformed."""self.record_once(lambda s: s.app.teardown_request_funcs.setdefault(self.name, []).append(f))return fdef teardown_app_request(self, f):"""Like :meth:`Flask.teardown_request` but for a blueprint. Such afunction is executed when tearing down each request, even if outside ofthe blueprint."""self.record_once(lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f))return fdef context_processor(self, f):"""Like :meth:`Flask.context_processor` but for a blueprint. Thisfunction 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 fdef app_context_processor(self, f):"""Like :meth:`Flask.context_processor` but for a blueprint. Such afunction 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 fdef app_errorhandler(self, code):"""Like :meth:`Flask.errorhandler` but for a blueprint. Thishandler is used for all requests, even if outside of the blueprint."""def decorator(f):self.record_once(lambda s: s.app.errorhandler(code)(f))return freturn decoratordef url_value_preprocessor(self, f):"""Registers a function as URL value preprocessor for thisblueprint. It's called before the view functions are called andcan modify the url values provided."""self.record_once(lambda s: s.app.url_value_preprocessors.setdefault(self.name, []).append(f))return fdef url_defaults(self, f):"""Callback function for URL defaults for this blueprint. It's calledwith the endpoint and values and should update the values passedin place."""self.record_once(lambda s: s.app.url_default_functions.setdefault(self.name, []).append(f))return fdef app_url_value_preprocessor(self, f):"""Same as :meth:`url_value_preprocessor` but application wide."""self.record_once(lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f))return fdef app_url_defaults(self, f):"""Same as :meth:`url_defaults` but application wide."""self.record_once(lambda s: s.app.url_default_functions.setdefault(None, []).append(f))return fdef errorhandler(self, code_or_exception):"""Registers an error handler that becomes active for this blueprintonly. Please be aware that routing does not happen local to ablueprint so an error handler for 404 usually is not handled bya blueprint unless it is caused inside a view function. Anotherspecial case is the 500 internal server error which is always lookedup from the application.Otherwise works as the :meth:`~flask.Flask.errorhandler` decoratorof the :class:`~flask.Flask` object."""def decorator(f):self.record_once(lambda s: s.app._register_error_handler(self.name, code_or_exception, f))return freturn decoratordef register_error_handler(self, code_or_exception, f):"""Non-decorator version of the :meth:`errorhandler` error attachfunction, akin to the :meth:`~flask.Flask.register_error_handler`application-wide function of the :class:`~flask.Flask` object butfor error handlers limited to this blueprint... versionadded:: 0.11"""self.record_once(lambda s: s.app._register_error_handler(self.name, code_or_exception, f))
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。