flask中url的本质:

吧url和视图函数封装到一个Rule对象里面去了,并且吧这个对象添加到url_map中
Rule={"url":'/index','method':'index'}
url_map = [{"url":'/index','method':'index'},{"url":'/index','method':'index'}]

第一步:

app = Flask(__name__)

第二步:实例化一个对象,执行构造方法

if self.has_static_folder:
self.add_url_rule(self.static_url_path + '/<path:filename>',
endpoint='static',
view_func=self.send_static_file)

第三步:

@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
#吧url和视图函数保存到了一个Rule对象中,并且把这个对象添加到了url_map列表中
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule)

第四步:

   url_rule_class = Rule

@implements_to_string
class Rule(RuleFactory): def __init__(self, string, defaults=None, subdomain=None, methods=None,
build_only=False, endpoint=None, strict_slashes=None,
redirect_to=None, alias=False, host=None):
if not string.startswith('/'):
raise ValueError('urls must start with a leading slash')
self.rule = string
self.is_leaf = not string.endswith('/') self.map = None
self.strict_slashes = strict_slashes
self.subdomain = subdomain
self.host = host
self.defaults = defaults
self.build_only = build_only
self.alias = alias
if methods is None:
self.methods = None
else:
if isinstance(methods, str):
raise TypeError('param `methods` should be `Iterable[str]`, not `str`')
self.methods = set([x.upper() for x in methods])
if 'HEAD' not in self.methods and 'GET' in self.methods:
self.methods.add('HEAD')
self.endpoint = endpoint
self.redirect_to = redirect_to if defaults:
self.arguments = set(map(str, defaults))
else:
self.arguments = set()
self._trace = self._converters = self._regex = self._argument_weights = None def empty(self):
"""
Return an unbound copy of this rule. This can be useful if want to reuse an already bound URL for another
map. See ``get_empty_kwargs`` to override what keyword arguments are
provided to the new copy.
"""
return type(self)(self.rule, **self.get_empty_kwargs()) def get_empty_kwargs(self):
"""
Provides kwargs for instantiating empty copy with empty() Use this method to provide custom keyword arguments to the subclass of
``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass
has custom keyword arguments that are needed at instantiation. Must return a ``dict`` that will be provided as kwargs to the new
instance of ``Rule``, following the initial ``self.rule`` value which
is always provided as the first, required positional argument.
"""
defaults = None
if self.defaults:
defaults = dict(self.defaults)
return dict(defaults=defaults, subdomain=self.subdomain,
methods=self.methods, build_only=self.build_only,
endpoint=self.endpoint, strict_slashes=self.strict_slashes,
redirect_to=self.redirect_to, alias=self.alias,
host=self.host) def get_rules(self, map):
yield self def refresh(self):
"""Rebinds and refreshes the URL. Call this if you modified the
rule in place. :internal:
"""
self.bind(self.map, rebind=True) def bind(self, map, rebind=False):
"""Bind the url to a map and create a regular expression based on
the information from the rule itself and the defaults from the map. :internal:
"""
if self.map is not None and not rebind:
raise RuntimeError('url rule %r already bound to map %r' %
(self, self.map))
self.map = map
if self.strict_slashes is None:
self.strict_slashes = map.strict_slashes
if self.subdomain is None:
self.subdomain = map.default_subdomain
self.compile() def get_converter(self, variable_name, converter_name, args, kwargs):
"""Looks up the converter for the given parameter. .. versionadded:: 0.9
"""
if converter_name not in self.map.converters:
raise LookupError('the converter %r does not exist' % converter_name)
return self.map.converters[converter_name](self.map, *args, **kwargs) def compile(self):
"""Compiles the regular expression and stores it."""
assert self.map is not None, 'rule not bound' if self.map.host_matching:
domain_rule = self.host or ''
else:
domain_rule = self.subdomain or '' self._trace = []
self._converters = {}
self._static_weights = []
self._argument_weights = []
regex_parts = [] def _build_regex(rule):
index = 0
for converter, arguments, variable in parse_rule(rule):
if converter is None:
regex_parts.append(re.escape(variable))
self._trace.append((False, variable))
for part in variable.split('/'):
if part:
self._static_weights.append((index, -len(part)))
else:
if arguments:
c_args, c_kwargs = parse_converter_args(arguments)
else:
c_args = ()
c_kwargs = {}
convobj = self.get_converter(
variable, converter, c_args, c_kwargs)
regex_parts.append('(?P<%s>%s)' % (variable, convobj.regex))
self._converters[variable] = convobj
self._trace.append((True, variable))
self._argument_weights.append(convobj.weight)
self.arguments.add(str(variable))
index = index + 1 _build_regex(domain_rule)
regex_parts.append('\\|')
self._trace.append((False, '|'))
_build_regex(self.is_leaf and self.rule or self.rule.rstrip('/'))
if not self.is_leaf:
self._trace.append((False, '/')) if self.build_only:
return
regex = r'^%s%s$' % (
u''.join(regex_parts),
(not self.is_leaf or not self.strict_slashes) and
'(?<!/)(?P<__suffix__>/?)' or ''
)
self._regex = re.compile(regex, re.UNICODE) def match(self, path, method=None):
"""Check if the rule matches a given path. Path is a string in the
form ``"subdomain|/path"`` and is assembled by the map. If
the map is doing host matching the subdomain part will be the host
instead. If the rule matches a dict with the converted values is returned,
otherwise the return value is `None`. :internal:
"""
if not self.build_only:
m = self._regex.search(path)
if m is not None:
groups = m.groupdict()
# we have a folder like part of the url without a trailing
# slash and strict slashes enabled. raise an exception that
# tells the map to redirect to the same url but with a
# trailing slash
if self.strict_slashes and not self.is_leaf and \
not groups.pop('__suffix__') and \
(method is None or self.methods is None or
method in self.methods):
raise RequestSlash()
# if we are not in strict slashes mode we have to remove
# a __suffix__
elif not self.strict_slashes:
del groups['__suffix__'] result = {}
for name, value in iteritems(groups):
try:
value = self._converters[name].to_python(value)
except ValidationError:
return
result[str(name)] = value
if self.defaults:
result.update(self.defaults) if self.alias and self.map.redirect_defaults:
raise RequestAliasRedirect(result) return result def build(self, values, append_unknown=True):
"""Assembles the relative url for that rule and the subdomain.
If building doesn't work for some reasons `None` is returned. :internal:
"""
tmp = []
add = tmp.append
processed = set(self.arguments)
for is_dynamic, data in self._trace:
if is_dynamic:
try:
add(self._converters[data].to_url(values[data]))
except ValidationError:
return
processed.add(data)
else:
add(url_quote(to_bytes(data, self.map.charset), safe='/:|+'))
domain_part, url = (u''.join(tmp)).split(u'|', 1) if append_unknown:
query_vars = MultiDict(values)
for key in processed:
if key in query_vars:
del query_vars[key] if query_vars:
url += u'?' + url_encode(query_vars, charset=self.map.charset,
sort=self.map.sort_parameters,
key=self.map.sort_key) return domain_part, url def provides_defaults_for(self, rule):
"""Check if this rule has defaults for a given rule. :internal:
"""
return not self.build_only and self.defaults and \
self.endpoint == rule.endpoint and self != rule and \
self.arguments == rule.arguments def suitable_for(self, values, method=None):
"""Check if the dict of values has enough data for url generation. :internal:
"""
# if a method was given explicitly and that method is not supported
# by this rule, this rule is not suitable.
if method is not None and self.methods is not None \
and method not in self.methods:
return False defaults = self.defaults or () # all arguments required must be either in the defaults dict or
# the value dictionary otherwise it's not suitable
for key in self.arguments:
if key not in defaults and key not in values:
return False # in case defaults are given we ensure taht either the value was
# skipped or the value is the same as the default value.
if defaults:
for key, value in iteritems(defaults):
if key in values and value != values[key]:
return False return True def match_compare_key(self): return bool(self.arguments), -len(self._static_weights), self._static_weights,\
-len(self._argument_weights), self._argument_weights def build_compare_key(self):
"""The build compare key for sorting. :internal:
"""
return self.alias and 1 or 0, -len(self.arguments), \
-len(self.defaults or ()) def __eq__(self, other):
return self.__class__ is other.__class__ and \
self._trace == other._trace __hash__ = None def __ne__(self, other):
return not self.__eq__(other) def __str__(self):
return self.rule @native_string_result
def __repr__(self):
if self.map is None:
return u'<%s (unbound)>' % self.__class__.__name__
tmp = []
for is_dynamic, data in self._trace:
if is_dynamic:
tmp.append(u'<%s>' % data)
else:
tmp.append(data)
return u'<%s %s%s -> %s>' % (
self.__class__.__name__,
repr((u''.join(tmp)).lstrip(u'|')).lstrip(u'u'),
self.methods is not None
and u' (%s)' % u', '.join(self.methods)
or u'',
self.endpoint
)
												

flask中路由的本质源码分析的更多相关文章

  1. RocketMQ中PullConsumer的启动源码分析

    通过DefaultMQPullConsumer作为默认实现,这里的启动过程和Producer很相似,但相比复杂一些 [RocketMQ中Producer的启动源码分析] DefaultMQPullCo ...

  2. Netty中NioEventLoopGroup的创建源码分析

    NioEventLoopGroup的无参构造: public NioEventLoopGroup() { this(0); } 调用了单参的构造: public NioEventLoopGroup(i ...

  3. RocketMQ中Broker的启动源码分析(一)

    在RocketMQ中,使用BrokerStartup作为启动类,相较于NameServer的启动,Broker作为RocketMQ的核心可复杂得多 [RocketMQ中NameServer的启动源码分 ...

  4. RocketMQ中Broker的启动源码分析(二)

    接着上一篇博客  [RocketMQ中Broker的启动源码分析(一)] 在完成准备工作后,调用start方法: public static BrokerController start(Broker ...

  5. RocketMQ中Broker的消息存储源码分析

    Broker和前面分析过的NameServer类似,需要在Pipeline责任链上通过NettyServerHandler来处理消息 [RocketMQ中NameServer的启动源码分析] 实际上就 ...

  6. JDK中String类的源码分析(二)

    1.startsWith(String prefix, int toffset)方法 包括startsWith(*),endsWith(*)方法,都是调用上述一个方法 public boolean s ...

  7. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  8. Flask系列10-- Flask请求上下文源码分析

    总览 一.基础准备. 1. local类 对于一个类,实例化得到它的对象后,如果开启多个线程对它的属性进行操作,会发现数据时不安全的 import time from threading import ...

  9. Flask - 请求处理流程和上下文源码分析

    目录 Flask - 请求处理流程和上下文 WSGI Flask的上下文对象及源码解析 0. 请求入口 1.请求上下文对象的创建 2. 将请求上下文和应用上下文入栈 3.根据请求的URl执行响应的视图 ...

随机推荐

  1. C# 7 out variables, tuples & other new features

    C# 7 out variables, tuples & other new features C# 7 is available on new Visual Studio 2017 and ...

  2. KMS11激活Window系列

    运行状态图 download: kms11

  3. 给X240换上了三键触摸板

    X240自带的触摸板非常不好用, 对于我这样的指点杆重度用户, 每次要按下整块板真的是太费力了, 而且在夜里声音很吵. 在淘宝上买了三键的X250的触摸板换上了. 这是购买的触摸板的型号 换的时候, ...

  4. ios判断是否有中文

    //判断是否有中文 -(BOOL)IsChinese:(NSString *)str { ; i< [str length];i++){ int a = [str characterAtInde ...

  5. (原+转)win7上编译caffe支持python及matlab

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/7126126.html 参考网址: https://github.com/happynear/caffe ...

  6. Spring MVC 教程,快速入门,深入分析[1-11]

    资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf SpringMVC核心配置文件示例.rar     作者:赵磊 博客:http://elf8848.iteye.com   ...

  7. [POST] What Is the Linux fstab File, and How Does It Work?

    If you’re running Linux, then it’s likely that you’ve needed to change some options for your file sy ...

  8. [转]NLP Tasks

    Natural Language Processing Tasks and Selected References I've been working on several natural langu ...

  9. hihocoder 1638:多级并查集

    题目链接 并查集可以用于聚类. import java.io.FileInputStream; import java.io.FileNotFoundException; import java.ut ...

  10. java hashcode的Delphi实现

    程序使用java做后台服务,数据处理时使用了java的hashcode,Delphi程序也需要生成这个hashcode,为了一致,所以要在Delphi下实现和Java一样的算法. 下面即Delphi版 ...