• python-flask-路由匹配源码分析


    @app.route('/')
    def hello_world():
        return 'Hello World!'

    第1步:

    class Flask(_PackageBoundObject):
        def route(self, rule, **options):
            def decorator(f):                 #f = hello_world
           #1.1获取别名
    endpoint
    = options.pop('endpoint', None)
           #1.2 self.add_url_rule(rule, endpoint, f,
    **options) return f return decorator

    第1.2步:

    class Flask(_PackageBoundObject):
        def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
            #1.2.1如果别名是None,执行_endpoint_from_view_func函数
            if endpoint is None:
                endpoint = _endpoint_from_view_func(view_func)
         #1.2.2 给endpoint赋值 options[
    'endpoint'] = endpoint
         #1.2.3 获取允许的请求方法 methods
    = options.pop('methods', None)      #1.2.4如果方法为None if methods is None:
           #默认为GET methods
    = getattr(view_func, 'methods', None) or ('GET',)
         #1.2.5如果方法是字符串,抛出异常: 必须是methods=["POST"]这样可迭代的
    if isinstance(methods, string_types): raise TypeError('Allowed methods have to be iterables of strings, ' 'for example: @app.route(..., methods=["POST"])')
         #1.2.6把方法变成大写 methods
    = set(item.upper() for item in methods)      #1.2.7把匹配url和允许请求的方法封装到了Rule的一个对象中 rule = self.url_rule_class(rule, methods=methods, **options)
         #self.url_rule_class = Rul
         #1.2.8
    self.url_map.add(rule)
          #self.url_map = Map()
    if view_func is not None:        #1.2.9 此步完成后: {"别名":被装饰的函数名} self.view_functions[endpoint] = view_func

    第1.2.1步:

    def _endpoint_from_view_func(view_func):
        #返回被装饰的函数名
        return view_func.__name__

    第1.2.8步:

    class Map(object):
        def add(self, rulefactory):
            #1.2.8.1
            for rule in rulefactory.get_rules(self):
           #1.2.8.2 Rule对象进行re正则绑定 rule.bind(self)
           #1.2.8.3 添加到self._rules列表中,此时列表中就有了url self._rules.append(rule)
           #1.2.8.4 此步完成后: {"别名":url} self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)

    第1.2.8.1步:

    class Rule(RuleFactory):
      def get_rules(self, map): yield self
       #返回Rule对

    第1.2.8.2步:

    class Rule(RuleFactory):
      def bind(self, map, rebind=False):
         #1.2.8.2.1
    self.compile()

    第1.2.8.2.1步: 看不懂,猜里面是把url进行了re正则处理

    class Rule(RuleFactory):
        def compile(self):
            if self.map.host_matching:
                domain_rule = self.host or ''
            else:
                domain_rule = self.subdomain or ''
    
            self._trace = []
            self._converters = {}
            self._static_weights = []
            self._argument_weights = []
            regex_parts = []
    
            def _build_regex(rule):
                index = 0
                for converter, arguments, variable in parse_rule(rule):
                    if converter is None:
                        regex_parts.append(re.escape(variable))
                        self._trace.append((False, variable))
                        for part in variable.split('/'):
                            if part:
                                self._static_weights.append((index, -len(part)))
                    else:
                        if arguments:
                            c_args, c_kwargs = parse_converter_args(arguments)
                        else:
                            c_args = ()
                            c_kwargs = {}
                        convobj = self.get_converter(
                            variable, converter, c_args, c_kwargs)
                        regex_parts.append('(?P<%s>%s)' % (variable, convobj.regex))
                        self._converters[variable] = convobj
                        self._trace.append((True, variable))
                        self._argument_weights.append(convobj.weight)
                        self.arguments.add(str(variable))
                    index = index + 1
    
            _build_regex(domain_rule)
            regex_parts.append('\|')
            self._trace.append((False, '|'))
            _build_regex(self.is_leaf and self.rule or self.rule.rstrip('/'))
            if not self.is_leaf:
                self._trace.append((False, '/'))
    
            if self.build_only:
                return
            regex = r'^%s%s$' % (
                u''.join(regex_parts),
                (not self.is_leaf or not self.strict_slashes) and
                '(?<!/)(?P<__suffix__>/?)' or ''
            )
            self._regex = re.compile(regex, re.UNICODE)

     到此为止:

    路由规则列表里新增了一条绑定正则的rule ;{"别名":rule} ;{"别名":被装饰的函数名}

  • 相关阅读:
    [视频教程] 如何在docker环境下的纯净ubuntu系统中安装最新版nginx
    [视频教程] 如何在Linux深度系统deepin下安装docker
    某业务自助开通账户问题排查
    将博客搬至CSDN
    某业务付费统计脚本问题排查
    [PHP] 存储改造中的逻辑和清理遗留的问题
    [PHP] 运维新增服务器导致的附件上传失败问题
    [PHP] 近期接手現有的企邮前端框架业务所遇困难
    [Linux] 编写Dockerfile文件自动构建镜像
    [PHP] 持续交付Jenkins安装
  • 原文地址:https://www.cnblogs.com/liuwei0824/p/8318181.html
Copyright © 2020-2023  润新知