Flask之Blueprint
来源:互联网 发布:网站程序和网站源码 编辑:程序博客网 时间:2024/05/25 01:35
Blueprint
Blueprint继承自_PackageBoundObject类
class Blueprint(_PackageBoundObject): warn_on_modifications = False _got_registered_once = False def __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 = name self.url_prefix = url_prefix self.subdomain = subdomain self.static_folder = static_folder self.static_url_path = static_url_path self.deferred_functions = [] if url_defaults is None: url_defaults = {} self.url_values_defaults = url_defaults
除了Blueprint名称和导入的模块名,其他参数都有默认值,因此Blueprint可以这样初始化:
# -*- coding: utf-8 -*-from flask import Blueprintauth = Blueprint("auth", __name__)import views
Blueprint实例创建之后,需要调用Flask.register_blueprint()进行注册,我们来分析这个函数的处理流程:
def register_blueprint(self, blueprint, **options): """Registers a blueprint on the application. .. versionadded:: 0.7 """ first_registration = False if blueprint.name in self.blueprints: assert self.blueprints[blueprint.name] is blueprint, \ 'A blueprint\'s name collision occurred between %r and ' \ '%r. Both share the same name "%s". Blueprints that ' \ 'are created on the fly need unique names.' % \ (blueprint, self.blueprints[blueprint.name], blueprint.name) else: self.blueprints[blueprint.name] = blueprint self._blueprint_order.append(blueprint) first_registration = True blueprint.register(self, options, first_registration)Flask有个列表blueprints,里面保存了所有Blueprint名,注册新的Blueprint时,首先以Blueprint为索引检查Flask列表blueprints,如果存在了,则给出告警;否则,将该Blueprint名称保存到列表blueprjints中,并调用Blueprint.register()进行深入注册。
继续分析Blueprint.register()处理流程:
def register(self, app, options, first_registration=False): """Called by :meth:`Flask.register_blueprint` to register a blueprint on the application. This can be overridden to customize the register behavior. Keyword arguments from :func:`~flask.Flask.register_blueprint` are directly forwarded to this method in the `options` dictionary. """ self._got_registered_once = True state = self.make_setup_state(app, options, first_registration) if self.has_static_folder: state.add_url_rule(self.static_url_path + '/<path:filename>', view_func=self.send_static_file, endpoint='static') for deferred in self.deferred_functions: deferred(state)如果Blueprint有自己的static目录,则把static目录也添加到Flask路由规则中
BlueprintSetupState
这个类是Blueprint和Flask类之间的临时粘合剂。对象变量分别有Blueprint和Flask的引用、可选参数、url前缀等。需要注意的是,这里的可选参数是一般是调用Flask.register_blueprint()时传入的,优先级要高于Blueprint的可选参数
class BlueprintSetupState(object): """Temporary holder object for registering a blueprint with the application. An instance of this class is created by the :meth:`~flask.Blueprint.make_setup_state` method and later passed to all register callback functions. """ def __init__(self, blueprint, app, options, first_registration): #: a reference to the current application self.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 self.first_registration = first_registration subdomain = self.options.get('subdomain') if subdomain is None: subdomain = self.blueprint.subdomain self.subdomain = subdomain url_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 the blueprint's name. """ if self.url_prefix: rule = self.url_prefix + rule options.setdefault('subdomain', self.subdomain) if endpoint is None: endpoint = _endpoint_from_view_func(view_func) defaults = self.url_defaults if '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)
初始化有几个地方需要注意(下面的可选参数都是调用Flask.register_blueprint()时传进来的):
- 如果可选参数中存在"url_prefix",则以可选参数为准,否则以Blueprint自带的"url_prefix"为准
- 如果可选参数中存在"subdomain",则以可选参数为准,否则以Blueprint自带的"subdomain"为准
BlueprintSetupState唯一对外提供的方法是 def add_url_rule(self, rule, endpoint=None, view_func=None, **options),该方法对url做些处理后,最终还是调用Flask的add_url_rule()来添加路由规则。这里我们之间查看Flask.add_url_rule()方法如何处理的:
class Flask(_PackageBoundObject): @setupmethod def add_url_rule(self, rule, endpoint=None, view_func=None, **options): if endpoint is None: endpoint = _endpoint_from_view_func(view_func) options['endpoint'] = endpoint methods = options.pop('methods', None) # if the methods are not given and the view_func object knows its # methods we can use that instead. If neither exists, we go with # a tuple of only ``GET`` as default. if methods is None: methods = getattr(view_func, 'methods', None) or ('GET',) if isinstance(methods, string_types): raise TypeError('Allowed methods have to be iterables of strings, ' 'for example: @app.route(..., methods=["POST"])') methods = set(item.upper() for item in methods) # Methods that should always be added required_methods = set(getattr(view_func, 'required_methods', ())) # starting with Flask 0.8 the view_func object can disable and # force-enable the automatic options handling. provide_automatic_options = getattr(view_func, 'provide_automatic_options', None) if provide_automatic_options is None: if 'OPTIONS' not in methods: provide_automatic_options = True required_methods.add('OPTIONS') else: provide_automatic_options = False # Add the required methods now. methods |= required_methods rule = self.url_rule_class(rule, methods=methods, **options) rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule) if view_func is not None: old_func = self.view_functions.get(endpoint) if old_func is not None and old_func != view_func: raise AssertionError('View function mapping is overwriting an ' 'existing endpoint function: %s' % endpoint) self.view_functions[endpoint] = view_func
- 如果没有提供endpoint,则获取路由函数的名称作为路由规则的endpoint(这里说明,每个路由规则必然带有一个endpoint)
- 如果没有提供可选参数“methods”,则默认以GET方法来装饰,所有方法转换为大写
- 生成路由规则rule,并且添加到url_map中
- 如果路由规则处理函数不为空,则添加到view_functions字典中,key就是endpoint,value则是路由处理函数
阅读全文
0 0
- Flask之Blueprint
- Flask-Blueprint
- flask-Blueprint
- flask Blueprint用法
- flask 中的蓝图 blueprint 的理解
- flask 中的蓝图 blueprint 的理解
- Flask 用Blueprint实现模块化的应用
- Python进阶(四十九)-初识Flask Blueprint
- python flask,file structure ,blueprint简单应用
- Blueprint入门之五
- Blueprint入门之四
- Blueprint入门之六
- blueprint
- Blueprint
- BLUEPRINT
- blueprint
- flask使用Blueprint进行多模块应用的编写
- Flask之Flask类
- css 背景设置和文本外观属性
- 【nginx-rtmp】10、指令(Directives)之 视频点播(Video on demand)
- Android关于界面一定时间无操作自动跳转到指定界面的实现
- 集合框架——数组和集合互相变换
- Android从相册选择图片并裁剪
- Flask之Blueprint
- Install wxPython2.8 in the Ubuntu16.04
- Sudoku (深搜)
- codeforces835 C
- 【hdu 4497】GCD and LCM 【算术基本定理】
- [bzoj2788][Poi2012]Festival floyd 差分约束系统 tarjan
- Android中touch事件机制学习总结
- 顶部标题栏在页面滚动后逐渐淡出
- c++ template报错