2. Flask应用对象与路由系统
在Flask中,一切请求处理都围绕一个核心对象展开——Flask 类实例。它既是 WSGI 应用本身,也是路由表、配置、扩展和请求上下文的容器。理解应用对象的创建方式,以及路由如何从装饰器一步步注册进 url_map,是掌握 Flask 后端工程的第一道门槛。
一、Flask 类实例化:应用对象的诞生
最简形式是 app = Flask(__name__)。这里的 __name__ 并非可有可无,它决定了 Flask 如何定位当前模块的根路径,从而正确解析 templates/ 与 static/ 目录。若在包内使用,通常传入包名;若使用工厂函数,则把创建逻辑封装进 create_app(),便于测试与多环境配置。
from flask import Flask
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
app.config["SECRET_KEY"] = "dev-only-key"
实例化时还可传入 static_folder、static_url_path、template_folder 等参数,用于自定义静态资源与模板位置。应用对象一旦创建,就拥有一个空的 url_map,等待路由注册。
二、路由装饰器:把函数绑定到 URL
Flask 使用 @app.route() 装饰器把视图函数注册到路由表。装饰器本质是调用 app.add_url_rule(),把规则、端点名和视图函数写入 url_map。默认端点名是函数名,因此同一模块内函数名不能重复。
@app.route("/")
def index():
return "home"
@app.route("/health")
def health():
return {"status": "ok"}
若需要自定义端点名,可写 @app.route("/about", endpoint="about_page")。端点名是 url_for() 反查 URL 的键,也是路由内部唯一标识,工程中建议保持语义清晰、避免与函数名冲突。
三、URL 变量规则:从静态路径到动态参数
路由中的尖括号部分表示变量,默认类型为字符串。Flask 支持 string、int、float、path、uuid 等转换器。类型转换器不仅约束匹配,还会把参数转换为对应 Python 类型后传给视图函数。
@app.route("/user/<int:user_id>")
def get_user(user_id):
return f"user={user_id}"
@app.route("/file/<path:filepath>")
def get_file(filepath):
return f"file={filepath}"
注意 int 只匹配非负整数,path 允许斜杠,适合文件路径。若同一路径存在多条规则,Flask 按注册顺序与具体性匹配,静态规则优先于动态规则。变量名必须与视图函数形参一致,否则会抛出类型错误。
四、HTTP 方法绑定:同一 URL 的多行为
默认路由只响应 GET,也可自动响应 HEAD 与 OPTIONS。通过 methods 参数可显式声明允许的方法。当同一 URL 需要区分 GET 与 POST 时,可在视图函数内用 request.method 分支,也可拆成两个端点。
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
return "do login"
return "show form"
若请求方法不在允许列表内,Flask 返回 405 Method Not Allowed。工程中建议把只读接口限制为 GET,把写操作限制为 POST/PUT/DELETE,并在 methods 中显式列出,避免隐式行为。
五、路由注册过程与 url_map 查看
路由注册发生在装饰器执行时,而不是首次请求时。每条规则包含:规则字符串、端点名、视图函数、允许方法、转换器信息。应用启动后可通过 app.url_map 查看全部规则,也可用 flask routes 命令在终端输出路由表。
# 终端查看
$ flask --app app routes
# 代码中查看
for rule in app.url_map.iter_rules():
print(rule.endpoint, rule.rule, sorted(rule.methods))
输出中常见 static 端点,这是 Flask 自动注册的静态资源路由。若发现某条路由未生效,优先检查:装饰器是否在应用创建之后执行、端点名是否重复、变量转换器是否匹配、方法是否包含在 methods 中。
上图把“应用对象 → 装饰器 → url_map → 请求匹配 → 方法判断”串成一条完整链路。可以看到,路由注册是启动期行为,请求匹配是运行期行为,两者通过 url_map 解耦。理解这一点,就能在排查 404、405 或参数类型错误时快速定位问题发生在哪一阶段。
app.url_map,或在 CI 中执行 flask routes,把路由表作为接口契约的一部分进行核对。对于动态参数,优先使用 int、uuid 等转换器,而不是在视图函数内手动做字符串解析,这样能让 404 在路由层就被正确拦截。
@app.route 写在 if __name__ == "__main__" 内部,导致使用 flask run 或 WSGI 服务器时路由未注册;或在工厂函数中先创建 app 再导入视图模块,造成循环导入。正确做法是让视图模块在应用创建后显式注册,或使用蓝图统一挂载。