Flask快速入门(3) — flask路由系统
目录
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'ok'
if __name__ == '__main__':
app.run()
从这个简单的代码入口,来剖析一下路由@app.route('/')
route():就是一个加在index()上的装饰器
def route(self, rule, **options): # rule:匹配规则,options参数字典
def decorator(f):
endpoint = options.pop("endpoint", None) # 如果option中有endpoint就取出,否则endpoint=None
self.add_url_rule(rule, endpoint, f, **options) # f就是装饰器装饰的视图函数 index
return f
return decorator
获取的信息:
(1)route传参时可以指定 endpoint = '别名'
,endpoint是给这个路由取的别名,用作反向解析,稍后再会介绍。没有传时为None。
(2)主要是执行了add_url_rule方法将匹配规定与视图函数的对应关系添加到路由中
add_url_rule():将匹配规定与视图函数的对应关系添加到路由
@setupmethod
def add_url_rule(self,rule,endpoint=None,view_func=None,provide_automatic_options=None,**options):
# 其中rule是必须要传入的,endpoint是别名,view_func是函数名
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func) # 如果没有别名就执行该函数,并且将视图函数当做参数传入了,稍后再看
options["endpoint"] = endpoint
methods = options.pop("methods", None) # 如果options中有methods则取出,否则为methods = None
# 如果methods为None的话,默认为view_func中的methods属性值,或者为('GET',)请求
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",)
# 如果methods是字符串类型,string_types=>(str, unicode),则抛出异常
if isinstance(methods, string_types):
raise TypeError(
"Allowed methods have to be iterables of strings, "
'for example: @app.route(..., methods=["POST"])'
)
# 循环遍历methods,并转成大写、去重
methods = set(item.upper() for item in methods)
required_methods = set(getattr(view_func, "required_methods", ()))
if provide_automatic_options is None:
provide_automatic_options = getattr(
view_func, "provide_automatic_options", None
)
if provide_automatic_options is None:
if "OPTIONS" not in methods:
provide_automatic_options = True
required_methods.add("OPTIONS")
else:
provide_automatic_options = False
methods |= required_methods
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule) # 添加匹配规则
if view_func is not None:
old_func = self.view_functions.get(endpoint) # 默认self.view_functions={},所以old_func=None
if old_func is not None and old_func != view_func:
raise AssertionError(
"View function mapping is overwriting an "
"existing endpoint function: %s" % endpoint
)
self.view_functions[endpoint] = view_func # 将 endpoint 与 view_func 对应。{endpoint:view_func}
一眼看到上面的源码是不是懵,在代码中相关的部分添加了注释。获取的信息:
(1)methods是定义该视图函数的请求方式,如果没有指定就默认为get方式
(2)methods传参是不能传字符串类型,应该设置:methods=('post',),参数不区分大小写,即'post'与‘POST’都可以传入
(3)将endpoint的值与函数名对应,比如endpoint='xxx':则相当于是给视图函数index取了一个别名。如果没有endpoint,执行_endpoint_from_view_func(view_func)
,endpoint=函数名
def _endpoint_from_view_func(view_func):
"""Internal helper that returns the default endpoint for a given
function. This always is the function name.
"""
assert view_func is not None, "expected view func if endpoint is not provided."
return view_func.__name__ # 返回的就是函数名
总结:
(1)路由本质上就是执行了add_url_rule函数,所以也可以通过该函数来添加路由app.add_url_rule('/',endpoint='xxx',view_func=index)
(2)endpoint:用来指定别名,没有指定就用函数名字
(3)methods:用来指定视图函数的请求方式,没有指定就默认为get方法
(4)url_for:通过别名来做反向路由解析
from flask import Flask, request,redirect,url_for
app = Flask(__name__)
app.debug =True
# @app.route('/')
def index():
return 'dasdk'
app.add_url_rule('/',endpoint='xxx',view_func=index) # 用来绑定路由
@app.route('/login',methods=['post','get'])
def login():
url = url_for('xxx') # 反向路由解析,url此时指向index视图函数
return redirect(url)
if __name__ == '__main__':
app.run()
典型写法
@app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')
默认转换器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
@app.route和app.add_url_rule参数
rule:url规则
view_func:视图函数名称
defaults = None:默认值,当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数
endpoint = None:名称,用于反向生成URL,即: url_for('名称')
methods = None:允许的请求方式,如:["GET", "POST"]
strict_slashes = None:对URL最后的“/”符号是否严格要求
'''
@app.route('/index', strict_slashes=False)
#访问http://www.xx.com/index/ 或http://www.xx.com/index均可
@app.route('/index', strict_slashes=True)
#仅访问http://www.xx.com/index
'''
#重定向到指定地址
redirect_to = None,
'''
@app.route('/index/<int:nid>', redirect_to='/home/<nid>')
'''
路由正则匹配
from flask import Flask, url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
class RegexConverter(BaseConverter):
# 自定义URL匹配正则表达式
def __init__(self,map,regex):
super(RegexConverter,self).__init__(map)
self.regex = regex
def to_python(self, value):
# 路由匹配时,匹配成功后传递给视图函数中参数的值
value += 'sb'
return value
def to_url(self, value):
# 使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
val = super(RegexConverter,self).to_url(value)
return val
app.url_map.converters['regex'] = RegexConverter
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
# 参数nid就是to_python返回的值
print(nid)
print(url_for('index',nid='888'))
return 'Index'
if __name__ == '__main__':
app.run()