• werkzeug/routing.py-Rule源码分析


    Rule类主要用来定义和表示一个URL的模式。主要定义了一些关键字参数,用来改变url的行为。例如:这个url可以接收的请求方法,url的子域名,默认路径,端点名称,是否强制有斜杠在末尾等等

    在最开始使用route()传递的option参数,最后都是传给了Rule这个类来处理的

    class Rule(RuleFactory):
        def __init__(self, string, defaults=None, subdomain=None, methods=None,
                     build_only=False, endpoint=None, strict_slashes=None,
                     redirect_to=None, alias=False, host=None):
            if not string.startswith('/'):
                raise ValueError('urls must start with a leading slash')
            self.rule = string
            self.is_leaf = not string.endswith('/')
    
            self.map = None
            self.strict_slashes = strict_slashes
            self.subdomain = subdomain
            self.host = host
            self.defaults = defaults
            self.build_only = build_only
            self.alias = alias
            if methods is None:
                self.methods = None
            else:
                if isinstance(methods, str):
                    raise TypeError('param `methods` should be `Iterable[str]`, not `str`')
                self.methods = set([x.upper() for x in methods])
                if 'HEAD' not in self.methods and 'GET' in self.methods:
                    self.methods.add('HEAD')
            self.endpoint = endpoint
            self.redirect_to = redirect_to
    
            if defaults:
                self.arguments = set(map(str, defaults))
            else:
                self.arguments = set()
            self._trace = self._converters = self._regex = self._argument_weights = None
    源代码

    参数解析:

    • string:一个有含有占位符的url路径(<converter(arguments):name>), converter是可选的(converter定义在Map里面),默认是字符串
    • defaults:可选项。在同一个endpoint下的一个字典格式的默认规则,如果你访问某个url的时候,这个url存在default配置,则会显示defaluts对用的url路径 例如:
     url_map = Map([
                    Rule('/all/', defaults={'page': 1}, endpoint='all_entries'),
                    Rule('/all/page/<int:page>', endpoint='all_entries')
                ])
    # 当用户访问``http://example.com/all/page/1`` h将会重定向到``http://example.com/all/``.
    • subdomain:用来定义这个rule的子域名规则的一个字符串。默认是disable的,用法如下
    url_map = Map([
                    Rule('/', subdomain='<username>', endpoint='user/homepage'),
                    Rule('/stats', subdomain='<username>', endpoint='user/stats')
                ])
    • methods:定义允许访问的方法。默认只允许get方法。在0.6.1版本中,会自动添加HEAD如果存在GET请求的话
    • bulid_only:True, 只创建url,而不会被匹配。一般用于静态文件的路径创建,不需要WSGI application处理的情况下
    • endpoint:这个url的端点名称,可以是任何类型。最好的选择是使用字符串表示,
    • strict_slashes:是否严格要求URL后面的斜杠。为这个URL重写Map里面的strict_slashes配置
    • redirect_to:重定向到其他地址。可以是一个字符串(其他url路径),也可以是一个可调用的对西对象。例如:
    def foo_with_slug(adapter, id):
        # ask the database for the slug for the old id.  this of
        # course has nothing to do with werkzeug.
        return 'foo/' + Foo.get_slug_for_id(id)
    
    url_map = Map([
        Rule('/foo/<slug>', endpoint='foo'),
        Rule('/some/old/url/<slug>', redirect_to='foo/<slug>'),  # 重定向到上面定义的路径
        Rule('/other/old/url/<int:id>', redirect_to=foo_with_slug)  # 重定向到foo_with_slug函数
    ])
    • alias:在同一个endpoint里面为rule serves定义一个别名
    • host:为整个host提供匹配规则。如果设置了host,则subdomain会是disabled状态

    函数体解析:

     1    def __init__(self, string, defaults=None, subdomain=None, methods=None,
     2                  build_only=False, endpoint=None, strict_slashes=None,
     3                  redirect_to=None, alias=False, host=None):
     4         # 判断url路径是否是斜线开头
     5         if not string.startswith('/'):
     6             # 抛出异常:urls必须以斜线开头
     7             raise ValueError('urls must start with a leading slash')
     8         self.rule = string
     9         self.is_leaf = not string.endswith('/')
    10 
    11         self.map = None
    12         self.strict_slashes = strict_slashes
    13         self.subdomain = subdomain
    14         self.host = host
    15         self.defaults = defaults
    16         self.build_only = build_only
    17         self.alias = alias
    18         # 对methods参数的判断
    19         if methods is None:
    20             self.methods = None
    21         else:
    22             if isinstance(methods, str):
    23                 raise TypeError('param `methods` should be `Iterable[str]`, not `str`')
    24             self.methods = set([x.upper() for x in methods])
    25             # 如果没有HEAD和有GET的时候,把HEAD添加到methods里面
    26             if 'HEAD' not in self.methods and 'GET' in self.methods:
    27                 self.methods.add('HEAD')
    28         self.endpoint = endpoint
    29         self.redirect_to = redirect_to
    30 
    31         if defaults:
    32             # 通过map对象以及str函数,取出defaulte中的每一个键,并设置成字符串格式。最终保存为set格式:{'abc'}
    33             self.arguments = set(map(str, defaults))
    34         else:
    35             self.arguments = set()
    36         self._trace = self._converters = self._regex = self._argument_weights = None

    在Map对象的add方法中调用了Rule对象的get_rules方法

    def get_rules(self, map):
        yield self

    在Map对象的app方法中调用了Rule类的bind方法

    这个方法主要用来绑定路由规则到map,并基于路由规则信息创建正则表达式

     1     def bind(self, map, rebind=False):
     2         # 判断这个rule的map属性是否已经被绑定过了map值
     3         if self.map is not None and not rebind:
     4             raise RuntimeError('url rule %r already bound to map %r' %
     5                                (self, self.map))
     6         # 把Map的对象赋值给self.map
     7         self.map = map
     8         # 判断属性,如果Rule对象中没有,则使用Map类中的
     9         if self.strict_slashes is None:
    10             self.strict_slashes = map.strict_slashes
    11         if self.subdomain is None:
    12             self.subdomain = map.default_subdomain
    13         # 调用Rule类的compile方法
    14         self.compile()

    bind方法最后调用了Rule类的compile方法

    这个方法主要用来编译和存储正则表达式

  • 相关阅读:
    style,currentStyle,getComputedStyle的区别和用法
    仿FLASH的图片轮换效果
    offset--BUG
    DIV的变高与变宽
    [SDOI2014]重建
    [SHOI2016]黑暗前的幻想乡
    「GXOI / GZOI2019」旅行者
    「GXOI / GZOI2019」旧词
    「PKUWC2018」随机算法
    「GXOI / GZOI2019」与或和
  • 原文地址:https://www.cnblogs.com/eric_yi/p/8325056.html
Copyright © 2020-2023  润新知