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. SLF4J warning or error messages and their meanings

    来自:http://www.slf4j.org/codes.html#StaticLoggerBinder The method o.a.commons.logging.impl.SLF4FLogFa ...

  2. 微信小程序尝鲜一个月现状分析

    概述 曾记得在微信小程序还没有上线的时候,大家都是翘首以待.希望在张小龙,在企鹅的带领下,走出差别于原生开发的还有一条移动开发的道路,我也是一直关注着.知道1月9号,微信小程序最终对外开放了,作为第一 ...

  3. (素材源代码) 猫猫学iOS 之UIDynamic重力、弹性碰撞吸附等现象牛逼Demo

    猫猫分享,必须精品 原创文章,欢迎转载. 转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243 一:效果 二:代码 #import "ViewCon ...

  4. 【Fanvas技术解密】HTML5 canvas实现脏区重绘

    先说明一下,fanvas是笔者在企鹅公司开发的,即将开源的flash转canvas工具. 脏区重绘(dirty rectangle)并不是一门新鲜的技术了,这在最早2D游戏诞生的时候就已经存在. 复杂 ...

  5. V-rep学习笔记:机器人模型创建1—模型简化

    要进行机器人仿真首先需要得到机器人的几何模型.我们可以直接通过VREP中提供的基本几何体来搭建一个简易的机器人[Menu bar --> Add --> Primitive shape - ...

  6. 奥比中光3D视觉传感器--OpenNI 2配置

    PrimeSense是Kinect一代的芯片供应商,位于以色列,也是开源体感开发包OpenNI 的维护者.自从被 Apple 收购后,销声匿迹,OpenNI 也停止更新.现在可以从网站http://s ...

  7. Redis从入门到精通:初级篇(转)

    原文链接:http://www.cnblogs.com/xrq730/p/8890896.html,转载请注明出处,谢谢 Redis从入门到精通:初级篇 平时陆陆续续看了不少Redis的文章了,工作中 ...

  8. linux常用命令全拼

    命令缩写: pwd:print work directory 打印当前目录 显示出当前工作目录的绝对路径 ps: process status(进程状态,类似于windows的任务管理器) 常用参数: ...

  9. 7216:Minecraft

    总时间限制: 1000ms内存限制: 65536kB 描述 Minecraft是一个几乎无所不能的沙盒游戏,玩家可以利用游戏内的各种资源进行创造,搭建自己的世界. 在Minecraft中,基本的建筑元 ...

  10. 修改windows默认的远程连接端口

    打开注册表,找到以下路径项,并修改为你想要的端口,重启服务器即可. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Serve ...