Flask 路由
Flask 路由路由(Routing)是 Web 框架最核心的功能之一,它决定了哪个 URL 由哪个函数处理。 Flask 路由是 Web 应用程序中将 URL 映射到 Python 函数的机制。 Flask 路由是 Flask 应用的核心部分,用于处理不同 URL 的请求,并将请求的处理委托给相应的视图函数。 以下是关于 Flask 路由的详细说明,包括路由的定义、参数、方法和规则等。 基础路由 使用 @app.route() ..
Tutorial detail pages default to noindex.
Flask 路由
路由(Routing)是 Web 框架最核心的功能之一,它决定了哪个 URL 由哪个函数处理。
Flask 路由是 Web 应用程序中将 URL 映射到 Python 函数的机制。
Flask 路由是 Flask 应用的核心部分,用于处理不同 URL 的请求,并将请求的处理委托给相应的视图函数。
以下是关于 Flask 路由的详细说明,包括路由的定义、参数、方法和规则等。
基础路由
使用 @app.route() 装饰器将 URL 路径绑定到视图函数:
实例
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() 函数。

变量规则
实际应用中,URL 通常包含动态部分,例如用户 ID、文章标题等。
Flask 使用 <变量名> 语法在 URL 中定义动态部分,对应参数会自动传给视图函数。
字符串变量(默认类型)
不指定类型时,变量默认为字符串,匹配除了斜线 / 以外的任意字符:
实例
@app.route("/user/<username>")
def show_user(username):
# 注意:username 可能包含恶意脚本,实际生产环境需要转义
return f"<h1>用户:{username}</h1>"
# 测试访问:
# /user/runoob → 页面显示 "用户:runoob"
# /user/RUNOOB → 页面显示 "用户:RUNOOB"
类型转换器
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 字符串 |
实例
@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。
尾斜线的重定向行为
URL 尾部的 / 对路由匹配行为有直接影响,这一点很多初学者会困惑。
实例
# 访问 /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,避免搜索引擎将同一页面索引两次。
URL 构建——url_for
url_for() 是 Flask 内置的 URL 生成函数,它根据视图函数名生成对应的 URL。
这比硬编码 URL 字符串有很多好处:
- 如果以后修改了 URL 路由,所有通过 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 中包含动态变量,将对应值作为关键字参数传入即可。
多余的未知参数会被自动拼接为查询字符串。
HTTP 方法
默认情况下,路由只响应 GET 请求。
通过 methods 参数可以指定允许的 HTTP 方法:
实例
app = Flask(__name__)
# 同一个 URL 同时响应 GET 和 POST 请求
@app.route("/login", methods=["GET", "POST"])
def login():
# 通过 request.method 判断当前请求类型
if request.method == "POST":
# 处理登录表单提交(POST 请求时执行)
username = request.form.get("username")
return f"<h1>欢迎回来,{username}!</h1>"
else:
# 显示登录表单(GET 请求时执行)
return """
<form method="post">
<input type="text" name="username" placeholder="用户名">
<input type="submit" value="登录">
</form>
"""
快捷方法装饰器
Flask 为常见的 HTTP 方法提供了简写装饰器,让代码更清晰:
实例
@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):
# 删除文章的 API
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 方法通常也会被自动处理。
同时绑定多个路由
同一个视图函数可以绑定多个路由:
实例
@app.route("/hello")
@app.route("/hello/<name>")
def greet(name=None):
# name 有默认值 None,当访问 /hello 时 name 为 None
if name is None:
return "<h1>Hello, World!</h1>"
return f"<h1>Hello, {name}!</h1>"
访问 /hello 时 name 取默认值 None,访问 /hello/runoob 时 name 为 "runoob"。