zoukankan      html  css  js  c++  java
  • 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()
    
  • 相关阅读:
    RegExp.$1
    Wide&Deep 模型学习教程
    docker 安装与使用的相关问题
    Centos 防火墙
    odoo ERP 系统安装与使用
    Linux 开机自动启动脚本
    intel RDT技术管理cache和memory_bandwidth
    tensorflow 中 inter_op 和 intra_op
    centos 7 安装 nginx 或 apache,及其比较
    Dependency injection in .NET Core的最佳实践
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11601029.html
Copyright © 2011-2022 走看看