Flask中 endpoint 解析

1. Flask route函数解析

@app.route('/user/<name>')
def user(name):
    return 'Hello, %s' % name

等价于

def user(name)
    return 'Hello, %s' % name
    
app.add_url_rule('/user/<name>', 'user', user)

add_url_rule函数在文档中的解释:

add_url_rule(*args, **kwargs)
Connects a URL rule. Works exactly like the route() decorator. If a view_func is provided it will be registered with the endpoint.

add_url_rule参数:

rule – the URL rule as string(匹配的路由地址)
endpoint – the endpoint for the registered URL rule. Flask itself assumes the name of the view function as endpoint
view_func – the function to call when serving a request to the provided endpoint(视图函数)
options – the options to be forwarded to the underlying Rule object. A change to Werkzeug is handling of method options. methods is a list of methods this rule should be limited to (GET, POST etc.). By default a rule just listens for GET (and implicitly HEAD). Starting with Flask 0.6, OPTIONS is implicitly added and handled by the standard request handling.

2. Flask 请求解析

假设用户访问http://www.example.com/user/eric,Flask会找到user函数,并传递name='eric',执行这个函数并返回值。
但是实际中,Flask真的是直接根据路由查询视图函数么?

在源码中可以发现:

  • 每个应用程序app都有一个view_functions,这是一个字典,存储endpoint-view_func键值对add_url_rule的第一个作用就是向view_functions中添加键值对(在应用程序run之前处理)
  • 每个应用程序app都有一个url_map,它是一个Map类(werkzeug/routing.py中),里面包含了一个列表列表元素是Role的实例(werkzeug/routing.py中)add_url_rule的第二个作用就是向url_map中添加Role的实例(在应用程序run之前处理)

我们可以通过一个例子来看:

app = Flask(__name__)

@app.route('/test', endpoint='Test')
def test():
    pass


@app.route('/', endpoint='index')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    print(app.view_functions)
    print(app.url_map)
    app.run()

运行程序结果:

{'static': <bound method Flask.send_static_file of <Flask 'flask-code'>>, 'Test': <function test at 0x10065e488>, 'index': <function hello_world at 0x10323d488>}

Map([<Rule '/test' (HEAD, OPTIONS, GET) -> Test>,
 <Rule '/' (HEAD, OPTIONS, GET) -> index>,
 <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

url_map存储的是url与endpoint的映射!
实际上,当请求传来一个url的时候,会先通过rule找到endpoint(url_map),然后再根据endpoint再找到对应的view_func(view_functions)。通常,endpoint的名字都和视图函数名一样。

实际上这个endpoint就是一个Identifier,每个视图函数都有一个endpoint,
当有请求来到的时候,用它来知道到底使用哪一个视图函数

3. Flask 视图重定向

在实际应用中,当需要在一个视图中跳转到另一个视图中的时候,经常会使用url_for(endpoint)去查询视图,而不是把地址硬编码到函数中。
这个时候,我们就不能使用视图函数名当endpoint去查询了

app = Flask(__name__)
app.register_blueprint(user, url_prefix='user')
app.register_blueprint(book, url_prefix='book')

以上注册2个蓝图

在user中(省略初始化过程):

# user.py

@user.route('/article')
def article():
    pass

在book中(省略初始化过程):

# book.py

@book.route('/article')
def article():
    pass

/article这个路由对应两个函数名一样的视图函数,但分别在两个蓝图中。当使用url_for(article)调用的时候(注意,url_for是通过endpoint查询url地址,然后找视图函数),Flask无法知道到底使用哪个蓝图下的endpoint,故需要如下定义:

url_for('user.article')

4. 参考

猜你喜欢

转载自www.cnblogs.com/yueyun00/p/12399223.html