0

在如下这段话中:

http://segmentfault.com/a/1190000002172627

url_for()唯一必须的参数就是endpoint名,也是每个路由的内部名。默认情况下,路由的endpoint是一个附加到视图函数的名称。在这个示例中,处理根URL的视图函数为index(),所以给url_for()的名称为index。

可以根据如下代码为参照进行解说:

  1. 路由的内部名字是什么?

  2. endpoint是一个附加到视图函数的名称,所以,endpoint名就是视图函数的名称么?

  3. 为什么需要endpoint参数的时候,需要把视图函数的名称传进去?

    @app.route('/', methods=['GET', 'POST'])
    def index():

       form = NameForm()
       if form.validate_on_submit():
           session['name'] = form.name.data
           return redirect(url_for('index'))
       return render_template('index.html', form=form, name=session.get('name'))

3个回答

2

概念

  • 路由规则表 url_map._rules

    • Rule 规则之一

      • 函数 / view function - 处理某个 endpoint/path 的视图函数。可简单理解为,处理某个/组 URL 的函数。

      • 终点 / endpoint - flask 内部的标识

      • 其他 / Rule 规则转换器、methods 之类的

流程:

  1. 创建 Rule/path

  2. 为 Rule/path 分配 endpoint

  3. 为 Rule/path 指定 view function.

重点

  1. 一个 request 进来的时候,是依据 rule/path 来定位到 app 内部的,也就是说:

    • 当用户请求 /a 时,会调用 /a 条路由规则指定的视图函数来处理这个请求。

    • 同理,/users/<string:username> 也是一样。

  2. 在 flask 的 url_map 路由表中,rule/pathendpoint 在路由规则表里都是唯一的

    • 尤其是 endpoint,如果重复会报错。

    • rule/path,虽然可以重复,但其实只有第一条会生效。

  3. 如果开发者没有在 @app.route 装饰器或 app.add_url_rule() 函数调用处指定 endpoint 的话,flask 会为这条 Rule 规则 指定一个默认的 endpoint,即这个 view function 的名字。

关系

  • 一个 view function,可以有多个 endpointrule。是个一对多的关系。

  • 反过来,一个 endpoint,只能有一个 rule, 也只能有一个 view function

答案与解释

现在,回头来看题主的疑问。

1 . 『路由的内部名字是什么?』

名字是:index

在题主所说的下面的这个视图中,endpoint/路由规则表内部名称是 index,因为并未在 @app.route 函数调用中显式指定 endpoint。

@app.route('/', methods=['GET', 'POST']) 
    def index():
        form = NameForm()
        if form.validate_on_submit():
            session['name'] = form.name.data
            return redirect(url_for('index'))
        return render_template('index.html', form=form, name=session.get('name'))

2 . 『endpoint 是一个附加到视图函数的名称,所以,endpoint名就是视图函数的名称么?』

不是。正如上面 重点 处所说,如果没有显式指定 endpoint,flask 会将视图函数的名称也即此处的 index 当作此路由规则的 endpoint。

3 . 『为什么需要endpoint参数的时候,需要把视图函数的名称传进去?』

并非是 视图函数的名称,其实是 endpoint 的名字,只不过正巧在某些时候,endpoint 的名字和视图函数的名称是一样的。

Demo

#!/usr/bin/env python3
# coding=utf-8
import flask

app = flask.Flask(__name__)


@app.route('/', endpoint="home")
def amihome():
    '''
    请尝试以  `/` 和 `/shajiquan` 两个路径来访问;
    '''
    return "View function: {view}. Endpoint: {endpoint}".format(view="amihome", endpoint=flask.request.endpoint)


# 给 app 添加一条 url rule, 指定 rule, endpoint, 但不指定 view function.
app.add_url_rule(rule='/shajiquan', endpoint="shajiquan", methods=["GET", "DELETE"])
# 为 endpoint="shajiquan" 指定 view function
app.view_functions['shajiquan'] = amihome


@app.route('/')
def miao():
    return "wu at: {}".format(flask.request.endpoint)


# 尝试取消注释
# app.view_functions['home'] = miao


if __name__ == '__main__':
    app.run(debug=True, port=8964)
1
回复 龙鸣

好像你没有点赞……

shajiquan · 2016年07月28日

展开评论
1

看这样一段代码

class LoginView(views.MethodView):
    def get(self):
        pass
    def post(self):
        pass
        
app.add_url_rule(
    '/login/',
    endpoint='login',
    view_func=LoginView.as_view(b'login'),
    methods=['POST', 'GET']
)

我们可以使用类的方式写路由,flask中把这种写法抽象成修饰器,函数名=endpoint

撰写答案