routing模块是url的路由系统。主要分为三个类:Rule类,创建URL规则;MAP放置一个由URL组成的列表;MapAdapter,如果map实例调用bind方法,会返回一个MapAdapter实例,这个实例可以利用map的方法,找到对应url的视图函数,返回视图函数的调用结果。
Rule类(部分源码):
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 #初始化一个map属性
def empty(self):
return type(self)(self.rule, **self.get_empty_kwargs()
def get_rules(self, map):
yield self #生成器,调用后返回自身,submain首先获取**rule**,接着获取生成器
def refresh(self):
self.bind(self.map, rebind=True)
def bind(self, map, rebind=False):
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 #将url绑定在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() #bind方法将rule绑定到self.map上面,那么rule就可以使用map实例的属性
def get_converter(self, variable_name, converter_name, args, kwargs):
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) #调用self.map的的方法获得url转换的方法
rule实例化时至少接受一个参数,其他的都是默认参数。这个类实现了match,build等方法。主要的方法有get_url
方法,这个方法重写了父类RuleFactory的方法,返回的是自身的生成器。这个方法与submain等其他的类的实现方法不同,在submain类中,这个类本身包含了rule类,故调用get_urls
方法首先获得rule实例,再一次调用get_url
得到一个生成器。
另外一个方法是bind
方法,这个方法将rule实例绑定到map实例上,绑定后的rule能够使用map属性的方法。
Map类(部分源码):
def add(self, rulefactory):
for rule in rulefactory.get_rules(self):
rule.bind(self)
self._rules.append(rule)
self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)
self._remap = True #add 方法将一个rule绑定到map上面
def bind(self, server_name, script_name=None, subdomain=None,
server_name = server_name.lower()
if self.host_matching:
if subdomain is not None:
raise RuntimeError('host matching enabled and a '
'subdomain was provided')
elif subdomain is None:
subdomain = self.default_subdomain
if script_name is None:
script_name = '/'
try:
server_name = _encode_idna(server_name)
except UnicodeError:
raise BadHost()
return MapAdapter(self, server_name, script_name, subdomain,
url_scheme, path_info, default_method, query_args) #绑定server_name,返回一个mapadpter实例
map类相当于一个存放Rule类的容器,实现的方法能对rule进行操作,也是url进入特定视图函数的中介。
MapAdapter(部分源码):
def __init__(self, map, server_name, script_name, subdomain,
url_scheme, path_info, default_method, query_args=None):
self.map = map
self.server_name = to_unicode(server_name)
script_name = to_unicode(script_name)
if not script_name.endswith(u'/'):
script_name += u'/'
self.script_name = script_name
self.subdomain = to_unicode(subdomain)
self.url_scheme = to_unicode(url_scheme)
self.path_info = to_unicode(path_info)
self.default_method = to_unicode(default_method)
self.query_args = query_args #构造函数存放请求url中的各个段
def dispatch(self, view_func, path_info=None, method=None, catch_http_exceptions=False):
try:
try:
endpoint, args = self.match(path_info, method) #调用match方法,math方法接受路径和请求方法获得endpoint和参数
except RequestRedirect as e:
return e
return view_func(endpoint, args)
except HTTPException as e:
if catch_http_exceptions:
return e
raise #这个函数调用路由函数,返回调用后的结果
MapAdapter主要是获取请求的url参数,将参数传递至相关视图函数中,进行处理。