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
)
												

最新文章

  1. ubuntu15 coreclr
  2. PHP中常见的提示对照表
  3. 简化版c语言文法
  4. TypeScript Handbook 1——基本类型(翻译)
  5. .NET设计规范————类型设计规范
  6. 利用IdentityServer3在ASP.NET 5和Angular中实现OAuth2 Implicit Flow
  7. el表达式的function标签
  8. SQL触发器、事务
  9. unity shader random number
  10. PPAS上运行pg_dump经过
  11. OpenSSH &#39;child_set_env()&#39;函数安全绕过漏洞
  12. 模块化的JavaScript开发的优势在哪里
  13. 【服务器运维】Windows Server 2008 R2 下配置证书服务器和HTTPS
  14. Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)
  15. JavaFX引入资源问题
  16. ThreadLocal源码分析:(三)remove()方法
  17. 分布式任务调度平台XXL-JOB搭建教程
  18. 一道题引出对LinkedList源码的研究
  19. CDH hive-1.1.0-cdh5.10.0 安装
  20. java 多线程断点下载功能

热门文章

  1. Struts2学习笔记四:深入拦截器
  2. std::accumulate使用的一个小细节
  3. windows下 jemalloc编译
  4. 转 安装PHP出现make: *** [sapi/cli/php] Error 1 解决办法
  5. Quartz.NET开源作业调度框架系列(四):Plugin Job-转
  6. 解决input 有多少个radio绑定change事件,手动触发就会执行多少次问题
  7. 网站PV、UV以及查看方法
  8. kubectl top查看k8s pod的cpu , memory使用率情况
  9. blktrace + blkparse + btt 分析IO
  10. oracle的decode函数