通常的使用Buleprint搭配RestFul API的方式使用
user = Buleprint("user",__name__)
_api = API(user)
_api.add_resouce(User,"/")
步骤一:
首先创建Buleprint
传入Buleprint实例化API,查看API代码
class Api(object):
def __init__(self,**):
if app is not None:
self.app = app
self.init_app(app)
def init_app(self, app):
# If app is a blueprint, defer the initialization
try:
app.record(self._deferred_blueprint_init)
# Flask.Blueprint has a 'record' attribute, Flask.Api does not
except AttributeError:
self._init_app(app)
else:
self.blueprint = app
步骤二:
这里的app此时是buleprint,接着注册resource
def add_resource(self, resource, *urls, **kwargs):
if self.app is not None:
self._register_view(self.app, resource, *urls, **kwargs)
else:
self.resources.append((resource, urls, kwargs))
步骤三:
调用_register_view()
def _register_view(self, app, resource, *urls, **kwargs):
for url in urls:
# If this Api has a blueprint
if self.blueprint:
# And this Api has been setup
if self.blueprint_setup:
# Set the rule to a string directly, as the blueprint is already
# set up.
self.blueprint_setup.add_url_rule(url, view_func=resource_func, **kwargs)
continue
else:
# Set the rule to a function that expects the blueprint prefix
# to construct the final url. Allows deferment of url finalization
# in the case that the associated Blueprint has not yet been
# registered to an application, so we can wait for the registration
# prefix
rule = partial(self._complete_url, url)
else:
# If we've got no Blueprint, just build a url with no prefix
rule = self._complete_url(url, '')
# Add the url to the application or blueprint
app.add_url_rule(rule, view_func=resource_func, **kwargs)
步骤四:
这里的app和buleprint是相等的,后面调用buleprint的add_url_rule方法进行url注册
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
self.record(lambda s: s.add_url_rule(rule, endpoint, view_func, **options))
def record(self, func):
self.deferred_functions.append(func)
步骤五:
这里将rule和view_func使用匿名函数封装添加到deferred_functions列表中去。
至此,关于user的蓝本设置完毕。接下来就是注册蓝本到全局url中去。
business_modules = [
"app.user:user"
]
def register_blueprints(app, blueprints: list):
for bp in blueprints:
module = import_string(bp)
app.register_blueprint(module, url_prefix="/" + bp.split(":")[1])
步骤六:
在这里,创建flask应用app的时候,调用register_buleprint注册蓝本。这里的module就是前面所创建的user(Buleprint的实例化)
def register_blueprint(self, blueprint, **options):
blueprint.register(self, options, first_registration)
步骤七:
调用Buleprint的register进行注册。这里的self是flask应用app
def register(self, app, options, first_registration=False):
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)
这里的state暂时不用管,下面会说到。在register方法中,可以看到这段代码。
for deferred in self.deferred_functions:
deferred(state)
其中self.deferred_functions是最开始实例化API的时候步骤四中生成的(匿名函数),在匿名函数中可以看见是调用了state.add_url_rule去注册url的。state是什么呢?
def make_setup_state(self, app, options, first_registration=False):
return BlueprintSetupState(self, app, options, first_registration)
可以看出state是BlueprintSetupState的实例,查看其add_url_rule方法。
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
if self.url_prefix is not None:
if rule:
rule = '/'.join((
self.url_prefix.rstrip('/'), rule.lstrip('/')))
else:
rule = self.url_prefix
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)
这里可以看出最后调用了app的add_url_rule进行注册的(这里也就是app注册路由的方法)