如何正确调用url_for并指定路径参数?
How to correctly call url_for and specify path parameters?
这是views.py中的函数:
@application.route("/students/<int:id>", methods=["GET", "POST"])
def students(id):
return render_template("students.html")
我在 HTML 页面上使用了此代码:
<a href="{{ url_for('students', id=student.id) }}">{{ student.id }}</a>
但是 url_for
正在生成这个:
http://127.0.0.1:5000/students?id=1
我想生成这个:
http://127.0.0.1:5000/students/1
请注意,我还有一个函数是在第一个函数之前编写的:
@application.route("/students")
def students():
return render_template("students.html", students=Student.query.all())
我认为url_for
正在使用这条路线。
问题是您有 2 个具有几乎相同模式的端点:
/students
/students/<int:id>
这就变成了以什么顺序定义这些端点的问题,因为调用 url_for('students', id=student.id)
可以在两个 :
上正确匹配
- 如果匹配
/students
first,如 url_for
文档中所述:“目标端点未知的可变参数作为查询参数附加到生成的 URL。。由于 id=1234
不是此端点上的已知参数,因此它成为查询参数 ?id=1234
.
- 如果匹配
/students/<int:id>
first,那么您将得到预期的 /students/1234
依赖端点的顺序是一种脆弱且 error-prone 的策略,所以如果您认为您应该重新排序端点定义,不,那不是正确的方法。
我推荐的是这些选项:
重命名函数以帮助区分 url_for
(和您的代码的读者)一个端点用于获取 所有 学生,以及另一个是通过 id 访问 一个 学生 。然后在 url_for
:
中明确调用正确的那个
@application.route("/students/<int:id>", methods=["GET", "POST"])
def student_by_id(id):
return {"student": id}
@application.route("/students")
def all_students():
return {"students": "all"}
<a href="{{ url_for('student_by_id', id=student.id) }}">{{ student.id }}</a>
与选项 1 类似,但不是重命名函数,pass-in 一个 endpoint=...
关键字参数到 route(...)
装饰器以指定不同的端点名称。有关详细信息,请参阅 the docs for the route
decorator and the section on URL Route Registrations。默认情况下,“如果未传递 endpoint
参数,路由的端点名称默认为视图函数的名称。”。所以在这里,将接受 id
的端点命名为 "student_by_id"
并在 url_for
.
中明确使用它
@application.route(
"/students/<int:id>",
methods=["GET", "POST"],
endpoint="student_by_id", # <---------
)
def students(id):
return {"student": id}
@application.route("/students")
def students():
return {"students": "all"}
<a href="{{ url_for('student_by_id', id=student.id) }}">{{ student.id }}</a>
将两者合并为 1 个端点。然后端点函数应首先检查是否指定了 id
。如果是,则只处理 1 名学生的处理。否则,处理所有学生的处理。 url_for
调用不需要更改。
@application.route("/students")
@application.route("/students/<int:id>", methods=["GET", "POST"])
def students(id=None):
if id:
return {"student": id}
else:
return {"students": "all"}
<a href="{{ url_for('students', id=student.id) }}">{{ student.id }}</a>
选择最适合您的一种。
作为旁注,, I also recommend not using id
as a parameter or variable name, because you might accidentally shadow the built-in id()
function。将其更改为 student_id
.
实际上可能更具可读性
这是views.py中的函数:
@application.route("/students/<int:id>", methods=["GET", "POST"])
def students(id):
return render_template("students.html")
我在 HTML 页面上使用了此代码:
<a href="{{ url_for('students', id=student.id) }}">{{ student.id }}</a>
但是 url_for
正在生成这个:
http://127.0.0.1:5000/students?id=1
我想生成这个:
http://127.0.0.1:5000/students/1
请注意,我还有一个函数是在第一个函数之前编写的:
@application.route("/students")
def students():
return render_template("students.html", students=Student.query.all())
我认为url_for
正在使用这条路线。
问题是您有 2 个具有几乎相同模式的端点:
/students
/students/<int:id>
这就变成了以什么顺序定义这些端点的问题,因为调用 url_for('students', id=student.id)
可以在两个 :
- 如果匹配
/students
first,如url_for
文档中所述:“目标端点未知的可变参数作为查询参数附加到生成的 URL。。由于id=1234
不是此端点上的已知参数,因此它成为查询参数?id=1234
. - 如果匹配
/students/<int:id>
first,那么您将得到预期的/students/1234
依赖端点的顺序是一种脆弱且 error-prone 的策略,所以如果您认为您应该重新排序端点定义,不,那不是正确的方法。
我推荐的是这些选项:
重命名函数以帮助区分
中明确调用正确的那个url_for
(和您的代码的读者)一个端点用于获取 所有 学生,以及另一个是通过 id 访问 一个 学生 。然后在url_for
:@application.route("/students/<int:id>", methods=["GET", "POST"]) def student_by_id(id): return {"student": id} @application.route("/students") def all_students(): return {"students": "all"}
<a href="{{ url_for('student_by_id', id=student.id) }}">{{ student.id }}</a>
与选项 1 类似,但不是重命名函数,pass-in 一个
中明确使用它endpoint=...
关键字参数到route(...)
装饰器以指定不同的端点名称。有关详细信息,请参阅 the docs for theroute
decorator and the section on URL Route Registrations。默认情况下,“如果未传递endpoint
参数,路由的端点名称默认为视图函数的名称。”。所以在这里,将接受id
的端点命名为"student_by_id"
并在url_for
.@application.route( "/students/<int:id>", methods=["GET", "POST"], endpoint="student_by_id", # <--------- ) def students(id): return {"student": id} @application.route("/students") def students(): return {"students": "all"}
<a href="{{ url_for('student_by_id', id=student.id) }}">{{ student.id }}</a>
将两者合并为 1 个端点。然后端点函数应首先检查是否指定了
id
。如果是,则只处理 1 名学生的处理。否则,处理所有学生的处理。url_for
调用不需要更改。@application.route("/students") @application.route("/students/<int:id>", methods=["GET", "POST"]) def students(id=None): if id: return {"student": id} else: return {"students": "all"}
<a href="{{ url_for('students', id=student.id) }}">{{ student.id }}</a>
选择最适合您的一种。
作为旁注,id
as a parameter or variable name, because you might accidentally shadow the built-in id()
function。将其更改为 student_id
.