欢迎光临
我们一直在努力

Flask入门教程(六):路由详解——URL与视图函数的映射艺术

1. 基础路由

使用 @app.route() 装饰器将 URL 路径绑定到视图函数:

from flask import Flask

app = Flask(__name__)

# 绑定根路径 "/"
@app.route("/")
def index():
return "这是首页"

# 绑定 "/hello" 路径
@app.route("/hello")
def hello():
return "Hello, RUNOOB!"

# 不同路径对应不同函数
@app.route("/about")
def about():
return "关于本站"

  • 访问 http://127.0.0.1:5000/hello 时,Flask 调用 hello() 函数

  • 访问 http://127.0.0.1:5000/about 时,Flask 调用 about() 函数

2. 变量规则

实际应用中,URL 通常包含动态部分,例如用户 ID、文章标题等。Flask 使用 <变量名> 语法在 URL 中定义动态部分,对应参数会自动传给视图函数。

字符串变量(默认类型)

不指定类型时,变量默认为字符串,匹配除了斜线 / 以外的任意字符:

# <username> 是动态变量,Flask 将其值作为 keyword 参数传递给视图函数
@app.route("/user/<username>")
def show_user(username):
return f"<h1>用户:{username}</h1>"

# 测试访问:
# /user/runoob → 页面显示 "用户:runoob"
# /user/RUNOOB → 页面显示 "用户:RUNOOB"

⚠️ 安全提示:username 可能包含恶意脚本,实际生产环境需要转义处理(后续模板章节会介绍自动转义)。

类型转换器

Flask 内置了多种转换器,通过 <类型:变量名> 语法指定:

转换器说明示例 URL匹配结果
string 默认,接受不包含 / 的文本 /user/runoob username = "runoob"
int 正整数 /post/42 post_id = 42
float 正浮点数 /price/19.99 price = 19.99
path 接受包含 / 的字符串 /file/a/b/c.txt filepath = "a/b/c.txt"
uuid UUID 格式字符串 /item/550e8400-e29b-41d4-a716-446655440000 item_id = UUID 对象

# int 转换器:只有数字才能匹配,/post/abc 会返回 404
@app.route("/post/<int:post_id>")
def show_post(post_id):
# post_id 的类型是 int,不是字符串
return f"<h1>文章 #{post_id}</h1>"

# path 转换器:可以匹配包含 / 的路径
@app.route("/file/<path:filepath>")
def show_file(filepath):
return f"<p>文件路径:{filepath}</p>"

# float 转换器:匹配浮点数
@app.route("/price/<float:amount>")
def show_price(amount):
return f"<p>价格:¥{amount}</p>"

# uuid 转换器:只接受标准 UUID 格式
@app.route("/item/<uuid:item_id>")
def show_item(item_id):
return f"<p>商品 ID:{item_id}</p>"

转换器不仅做类型验证,还会自动将匹配的值转换成对应 Python 类型。例如 <int:post_id> 传给视图函数的是 int 而不是 str。

3. 尾斜线的重定向行为

URL 尾部的 / 对路由匹配行为有直接影响,这一点很多初学者会困惑。

# 规则 1:以 / 结尾——类似目录
# 访问 /projects 会自动 308 重定向到 /projects/
@app.route("/projects/")
def projects():
return "项目列表页面"

# 规则 2:不以 / 结尾——类似文件
# 访问 /about/ 会返回 404 Not Found
@app.route("/about")
def about():
return "关于页面"

路由定义访问 /projects访问 /projects/
@app.route("/projects/") 308 重定向到 /projects/ 正常返回
@app.route("/about") 正常返回 404 Not Found

这个设计对 SEO 有帮助:确保同一内容只有一个标准 URL,避免搜索引擎将同一页面索引两次。

4. URL 构建——url_for()

url_for() 是 Flask 内置的 URL 生成函数,它根据视图函数名生成对应的 URL。这比硬编码 URL 字符串有很多好处:

  • 如果以后修改了 URL 路由,所有通过 url_for 生成的地方自动更新

  • 自动处理特殊字符的转义

  • 生成的路径始终是绝对路径(相对站点根路径)

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/")
def index():
return "首页"

@app.route("/login")
def login():
return "登录页面"

@app.route("/user/<username>")
def profile(username):
return f"{username} 的个人主页"

# 使用 test_request_context() 来模拟请求上下文
# 这样 url_for() 才能正确生成 URL
with app.test_request_context():
print(url_for("index")) # 输出 /
print(url_for("login")) # 输出 /login
print(url_for("login", next="/")) # 输出 /login?next=%2F
print(url_for("profile", username="runoob")) # 输出 /user/runoob

规则说明
url_for() 的第一个参数 视图函数名(不是 URL 路径)
URL 中包含动态变量 将对应值作为关键字参数传入
多余的未知参数 自动拼接为查询字符串

5. HTTP 方法

默认情况下,路由只响应 GET 请求。通过 methods 参数可以指定允许的 HTTP 方法:

from flask import Flask, request

app = Flask(__name__)

# 同一个 URL 同时响应 GET 和 POST 请求
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username")
return f"<h1>欢迎回来,{username}!</h1>"
else:
return """
<form method="post">
<input type="text" name="username" placeholder="用户名">
<input type="submit" value="登录">
</form>
"""

methods 参数是一个列表,可以同时指定多个方法,如 ["GET", "POST", "PUT"]。

6. 快捷方法装饰器

Flask 为常见的 HTTP 方法提供了简写装饰器,让代码更清晰:

# 等价于 @app.route("/login", methods=["GET"])
@app.get("/login")
def login_form():
return "<form>…</form>"

# 等价于 @app.route("/login", methods=["POST"])
@app.post("/login")
def login_submit():
return "登录成功"

# 还支持 @app.put()、@app.delete()、@app.patch()
@app.delete("/post/<int:post_id>")
def delete_post(post_id):
return f"文章 {post_id} 已删除"

快捷装饰器等价写法典型用途
@app.get("/path") @app.route("/path", methods=["GET"]) 获取数据、显示页面
@app.post("/path") @app.route("/path", methods=["POST"]) 创建数据、提交表单
@app.put("/path") @app.route("/path", methods=["PUT"]) 更新数据(完整替换)
@app.delete("/path") @app.route("/path", methods=["DELETE"]) 删除数据
@app.patch("/path") @app.route("/path", methods=["PATCH"]) 更新数据(部分更新)

自动处理:如果路由定义了 GET 方法,Flask 会自动添加对 HEAD 方法的支持。同时 OPTIONS 方法也会被自动处理。

7. 同时绑定多个路由

同一个视图函数可以绑定多个路由:

# 两个不同的 URL 指向同一个视图函数
@app.route("/hello")
@app.route("/hello/<name>")
def greet(name=None):
if name is None:
return "<h1>Hello, World!</h1>"
return f"<h1>Hello, {name}!</h1>"

  • 访问 /hello 时,name 取默认值 None,显示 "Hello, World!"

  • 访问 /hello/runoob 时,name 为 "runoob",显示 "Hello, runoob!"

8. 路由匹配优先级

当多个路由匹配同一个 URL 时,Flask 按照定义顺序进行匹配,先定义的路由优先级更高:

@app.route("/user/<username>")
def show_user(username):
return f"普通用户:{username}"

@app.route("/user/admin")
def show_admin():
return "管理员页面"

如果上面的代码调换了顺序,访问 /user/admin 时 show_user 会先匹配到(将 "admin" 视为普通用户名),导致 show_admin 永远无法被访问。因此,更具体的路由应该定义在更通用的路由之前。

9. 路由常用模式速查表

场景代码
静态路由 @app.route("/about")
动态字符串 @app.route("/user/<username>")
动态整数 @app.route("/post/<int:post_id>")
动态路径 @app.route("/file/<path:filepath>")
指定方法 @app.route("/submit", methods=["POST"])
快捷方法 @app.post("/submit")
多路由绑定 @app.route("/hello") + @app.route("/hello/<name>")
URL生成 url_for("profile", username="runoob")

小结

本章全面讲解了 Flask 的路由系统。基础路由使用 @app.route() 装饰器绑定 URL;变量规则通过 <变量名> 和类型转换器实现动态 URL 匹配;尾斜线决定了是重定向还是返回 404;url_for() 动态生成 URL,便于维护;methods 参数和快捷装饰器控制 HTTP 方法;同一视图可绑定多个路由。这些机制共同构成了 Flask 灵活而强大的路由体系,是后续开发的基础。

赞(0)
未经允许不得转载:171主机测评 » Flask入门教程(六):路由详解——URL与视图函数的映射艺术
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址