Flask系列 路由系统
Flask路由系统细分from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'ok' if __name__ == '__main__': app.run() 从这个简单的代码入口,来剖析一下路由 route():就是一个加在index()上的装饰器?```python 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 获取的信息: add_url_rule():将匹配规定与视图函数的对应关系添加到路由@setupmethod def add_url_rule(self,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} 一眼看到上面的源码是不是懵,在代码中相关的部分添加了注释。获取的信息: 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函数,所以也可以通过该函数来添加路由 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() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |