路由内部实现+自定义转换器
from flask import Flask
app = Flask(__name__)
@app.route('/<int:news_id>',methods=['GET']) #int:转换器
def detail(news_id):
return 'ok'
@app.route('/',methods=['POST'])
def index():
return 'index'
if __name__ == '__main__':
print(app.url_map) # 输出app.url_map属性
app.run()
在app中有个属性:url_map , 输出 app.url.map
Map([
<Rule '/' (OPTIONS, POST) -> index>,
<Rule '/<news_id>' (OPTIONS, GET, HEAD) -> detail>
# Flask自动添加,用于静态文件的路径,当我们在setting文件中指定静态路径时,根据下面路由去查找静态文件。
<Rule '/static/<filename>'(OPTIONS, GET, HEAD) -> static
])
输出一个Map对象,Map对象里面有多个Rule对象,Rule对象里面的结构是< Rule '请求地址' --->请求方法 ---> 对象的视图函数>
那么现在我们想看一下Map对象是什么?以及Rule对象里面是什么? 我们先输出Map对象的类型
-
if __name__ == '__main__': print(app.url_map) # 输出app.url_map属性 print(type(app.url_map)) #输出app.url_map对象的类型 app.run() 输出: <class 'werkzeug.routing.Map'>
可以看出Map对象是werkzeug模块下面的一个对象,那么werkzeug是什么呢?
-
Flask框架由两个核心组成
-
werkzeug
-
jinjia2
-
Flask是在werkzeug模块的基础之上进行开发,werkzeug库的routing模块赋值实现URL解析,下面可以更好的看清Flask框架的组成。
进入Map类源码:
class Map(object):
default_converters = ImmutableDict(DEFAULT_CONVERTERS) # 默认的转换器
def __init__(self, rules=None, default_subdomain='', charset='utf-8',
strict_slashes=True, redirect_defaults=True,
converters=None, sort_parameters=False, sort_key=None,
encoding_errors='replace', host_matching=False):
self._rules = [] # 创建了一个Rules列表对象
elf._rules_by_endpoint = {}
self._remap = True
self._remap_lock = Lock()
self.default_subdomain = default_subdomain
self.charset = charset
self.encoding_errors = encoding_errors
self.strict_slashes = strict_slashes
self.redirect_defaults = redirect_defaults
self.host_matching = host_matching
self.converters = self.default_converte rs.copy() # 将默认的转化器copy到Map对象中
if converters:
self.converters.update(converters)
self.sort_parameters = sort_parameters
self.sort_key = sort_key
for rulefactory in rules or ():
self.add(rulefactory)
- 在第一行有定义默认的转换器,default_converters = ImmutableDict(DEFAULT_CONVERTERS)
- 进入DEFAULT_CONVERTERS
#: the default converter mapping for the map
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
- 可以看出,当我们在url中设置了转化器int @app.route('/<int:news_id>',methods=['GET']) , int是什么东西?在这里就定义了
- 'int': IntegerConverter, 默认是字符串类型,那么IntegerConverter又是什么?进入IntegerConverter
class IntegerConverter(NumberConverter): # 继承至NumberConverter
regex = r'\d+' # 正则表达式
num_convert = int
也就是说int是一个正则表达式,当有请求url时,Flask会完成以下步骤
- 创建Rule对象 <Rule '/<int:news_id>' (OPTIONS, POST) -> index>
- 创建Map对象,将Rule对象添加进去Map([ <Rule '/<news_id>' (OPTIONS, GET, HEAD) -> detail>])
- 内置转换器,还会将装换器也添加进Map对象中
- 为app.url_map属性赋值
当有url请求时:
- 验证正则表达式
- 验证请求方式
- 调用视图函数
自定义转化器
1, 定义一个类继承至 NumberConverter
class IntegerConverter(NumberConverter):
regex = r"\d+" # 自定义正则
num_convert = int
2, app.url_map.converters['int']= IntegerConverter 将转换器添加至url_map对象的converters属性