url->views,实现原理

Flask中的 路由设置与django的有很大的区别,因为,Flask的轻量级,所以,Flask的用法会更简单:

在views上面加上装饰器,app.route() 即可。url的命名,反向解析,接受的请求的格式的处理,这一切都只需要填写参数即可。

route()的源码:

    def route(self, rule, **options):
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

"""
可以看见,这个装饰器,本身执行的是 decorator方法,
在decorator中,调用了 add_url_rule 方法。
从方法的字面意思上理解,就是添加 url 到rule去。
下面看一下 add_url_rule的代码:
"""

    def add_url_rule(self, rule, endpoint=None, view_func=None,
                     provide_automatic_options=None, **options):
        
        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options['endpoint'] = endpoint
        methods = options.pop('methods', None)

        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)

        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)
            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

看到上面的代码可以知道,Flask 建立url——》view 路由视图关系 正真的执行的是 add_url_rule() 函数,

并且,将路由(“/index”)这个封装了一个 Rule类,最后全部封装到了 url_map 里面。

所以,如果想要添加一个路由关系, 除了加装饰器之外还可以直接调用这个方法:

示例:

from flask import Flask

app = Flask(__name__)
app.config["DEBUG"] = True


def index():
    
    return "index"

app.add_url_rule("/index", f=index)


if __name__ == "__main__":
    app.run()

 

视图函数详解

- app.route()参数解析:

  - rule: 路径; 字符串形式的例如: "/index"

    - 路径添加参数:@app.route("/index/<int:id>"): 

      表示 从将id 传入视图函数, 且必须为int类型;

      当有参数的时候, 在反向解析的时候, 需要将参数传入 例:url_for("index", nid=999 )

示例:

from flask import Flask

app = Flask(__name__)
app.config["DEBUG"] = True

@app.route("/index/<int:id>")
def index(id):
    print(id, type(id))
    return "index"

if __name__ == "__main__":
    app.run()

 

    - 自定义路由中的参数类型:

      - 自定义一个继承 BaseConverter 的类 从werkzeug.routing 中导入。

      - app.url_map.converters["reg"] = 自定义的类
      - 在app.route("/index/<reg(\d+):nid>")中使用。
      - 当请求进来时会先实例化自定义的类,并且将nid的值传入到类中的to_python 函数中并调用
      - 当在反向生成url的时候会执行 to_url 的函数,也就是说在CBV中的 url_for() 会先执行to_url 函数。

      - 示例:

from flask import Flask
from werkzeug.routing import BaseConverter


class MyConverter(BaseConverter):
    def __init__(self, map, regex):
        super(MyConverter, self).__init__(map)
        self.regex = regex

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value:
        :return:
        """
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value:
        :return:
        """
        val = super(MyConverter, self).to_url(value)
        return val


app = Flask(__name__)
app.url_map.converters['reg'] = MyConverter


@app.route('/index/<reg("\d+"):nid>')
def index(nid):
    print(nid, type(nid))
    print(url_for('index', nid=987))
    return "index"


if __name__ == '__main__':
    app.run()
自定义路由中的参数类型

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-29
  • 2021-06-05
  • 2020-03-19
  • 2021-09-15
猜你喜欢
  • 2021-10-13
  • 2021-12-08
  • 2022-12-23
  • 2021-11-02
  • 2022-12-23
  • 2022-12-23
  • 2021-05-13
相关资源
相似解决方案