zoukankan      html  css  js  c++  java
  • flask_之URL

    URL篇

    在分析路由匹配过程之前,我们先来看看 flask 中,构建这个路由规则的两种方法:

    1. 通过 @app.route() decorator

    2. 通过 app.add_url_rule,这个方法的签名为 add_url_rule(self, rule, endpoint=None, view_func=None, **options),参数的含义如下:

      • rule: url 规则字符串,可以是静态的 /path,也可以包含 /

      • endpoint:要注册规则的 endpoint,默认是 view_func 的名字

      • view_func:对应 url 的处理函数,也被称为视图函数

    这两种方法是等价的,也就是说:

    @app.route('/')
    def hello():
        return "hello, world!"
    

     也可以写成

    def hello():
        return "hello, world!"
    
    app.add_url_rule('/', 'hello', hello)
    

     其实,还有一种方法来构建路由规则——直接操作 app.url_map 这个数据结构。不过这种方法并不是很常用,因此就不展开了

    静态路由

    @app.route('/')
    def hello_world():
        # 变量可以通过赋值传到前端,前端可以通过Jinja语法{{}}渲染
        return render_template('t1.html', name='t1', age=16)
    
    @app.route('/services')
    def services():
        return 'Services'
    @app.route('/about')
    def about():
        return 'About'
    
    # 相对projects解释类似于文件夹解释形式,指向某一个文件夹下的某个文件
    @app.route('/projects/')
    @app.route('/projects_our') # 可以定义多个URL到同一个视图函数上,Flask支持
    def projects():
        return 'Projects'
    
    @app.route('/login',methods=["GET","POST"])
    def login():
        return render_template('login.html', req_method=request.method)
    

     动态路由

    # 动态路由
    @app.route('/user/<username>')
    def user(username):
        print username
        return username
    
    # 路由转换器:指定参数类型
    # flask提供3种:int(整形)|float(浮点型)|path(路径,并支持一个/)
    @app.route('/user/<int:user_id>')
    def user(user_id):
        print user_id
        return 'User_id:%s'%user_id
    

     自定义路由规则

    # flask不提供正则表达的形式的URL匹配
    # 可通过定义完成
    # 1、from werkzeug.routing import BaseConverter
    # 2、自定义类
    #转换器
    class RegexConverter(BaseConverter):
        def __init__(self,url_map,*items):
            super(RegexConverter,self).__init__(self)
            # print items # (u'[a-z]{3}[A-Z]{3}',)
            # print url_map # URL 的一个MAP对象,类似路由表
            self.regex = items[0]
    
    # 3、要将定义的类注册到APP的url_map中,定义名称
    # app.url_map.converters['regex'] = RegexConverter
    
    # 4、使用
    @app.route('/user/<regex("[a-z]{3}[A-Z]{3}"):username>')
    def user(username):
        print username
        return 'Username:%s' % username
    

     浅析源码

    注册路由规则的时候,flask 内部做了哪些东西呢?我们来看看 route 方法:

    def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as :meth:`add_url_rule`
        but is intended for decorator usage.
        """
    
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
    
        return decorator
    route

    route 方法内部也是调用 add_url_rule,只不过在外面包了一层装饰器的逻辑,这也验证了上面两种方法等价的说法

    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        """Connects a URL rule.  Works exactly like the :meth:`route`
        decorator.  If a view_func is provided it will be registered with the
        endpoint.
        """
            if endpoint is None:
                endpoint = _endpoint_from_view_func(view_func)
            options['endpoint'] = endpoint
            methods = options.pop('methods', None)
    
            # if the methods are not given and the view_func object knows its
            # methods we can use that instead.  If neither exists, we go with
            # a tuple of only ``GET`` as default.
            if methods is None:
                methods = getattr(view_func, 'methods', None) or ('GET',)
            if isinstance(methods, string_types):
                raise TypeError('Allowed methods have to be iterables of strings, '
                                'for example: @app.route(..., methods=["POST"])')
            methods = set(item.upper() for item in methods)
    
            # Methods that should always be added
            required_methods = set(getattr(view_func, 'required_methods', ()))
    
            # starting with Flask 0.8 the view_func object can disable and
            # force-enable the automatic options handling.
            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
    
            # Add the required methods now.
            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)
                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
    add_url_rule

    上面这段代码省略了处理 endpoint 和构建 methods 的部分逻辑,可以看到它主要做的事情就是更新 self.url_mapself.view_functions 两个变量。找到变量的定义,发现 url_mapwerkzeug.routeing:Map 类的对象,rulewerkzeug.routing:Rule 类的对象,view_functions 就是一个字典。这和我们之前预想的并不一样,这里增加了 RuleMap 的封装,还把 urlview_func 保存到了不同的地方。

    需要注意的是:每个视图函数的 endpoint 必须是不同的,否则会报 AssertionError

    未完待续。。。

  • 相关阅读:
    C#中TreeView组件使用方法初步
    DataList编辑、更新、取消、删除、分页
    使用JMeter做web应用的压力测试
    再读Struts1.3.5 User Guide 3 Building Control Components
    Tomcat DBCP Connection Pool Abandon Feature
    在Linux调试web应用时,如何查看System.out.println的输出?
    再读Struts1.3.5 User Guide 4 Configuring Applications
    一篇关于web.xml配置的详细说明
    再读Struts1.3.5 User Guide 1 Building Model Components
    Struts下html:select可以多选时的处理方法
  • 原文地址:https://www.cnblogs.com/shangpolu/p/7103165.html
Copyright © 2011-2022 走看看