路由与视图函数:路由定义、动态路由、URL构建(url_for)、HTTP方法
各位同学,今天我们来聊聊 Flask 里最核心、最基础的东西——路由与视图函数。说白了,这就是你后端应用的「门牌号系统」。用户访问哪个地址,该由哪段代码来处理,全看路由怎么配。
我个人习惯把路由理解成一张「地图」。你定义好路径,Flask 就知道把请求送到哪个函数手里。这个机制看起来简单,但用好了,能让你的项目结构清晰十倍。
一、路由定义:最基础的玩法
先看一个最简单的例子。你写一个 Flask 应用,想让用户访问根路径 / 时看到一句话:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '欢迎来到我的小站'
if __name__ == '__main__':
app.run(debug=True)
这里 @app.route('/') 就是路由装饰器。它告诉 Flask:当用户访问 / 时,执行下面的 index() 函数。这个函数我们叫它「视图函数」。
嗯,这里要注意:视图函数必须返回一个响应。可以是字符串、HTML、JSON,或者后面我们会讲到的模板。总之不能返回 None,否则 Flask 会报错。
二、动态路由:让 URL 活起来
静态路由只能处理固定路径。但实际项目中,URL 往往是动态的。比如用户个人主页:/user/zhangsan、/user/lisi。难道要为每个用户写一个路由?当然不。
Flask 提供了动态路由,用 <变量名> 来捕获 URL 中的可变部分:
@app.route('/user/<username>')
def user_profile(username):
return f'你好,{username}!欢迎来到你的主页。'
访问 /user/小明,视图函数就会收到 username='小明'。是不是很直观?
动态路由还支持类型转换器。比如你想限制参数必须是整数:
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'你正在查看第 {post_id} 篇文章'
Flask 内置了几种转换器:
| 转换器 | 说明 | 示例 |
|---|---|---|
| string | 默认,接受任何不包含斜杠的文本 | /user/<string:name> |
| int | 接受正整数 | /post/<int:id> |
| float | 接受正浮点数 | /price/<float:amount> |
| path | 类似 string,但可以接受斜杠 | /path/<path:subpath> |
| uuid | 接受 UUID 字符串 | /item/<uuid:item_id> |
<path:url> 来捕获完整路径,结果忘记处理路径中的特殊字符,导致某些 URL 解析失败。后来我加了一层 URL 编码/解码才搞定。记住:path 转换器虽然方便,但要注意安全过滤。
三、URL 构建:用 url_for 反查路径
写代码时,我们经常需要生成某个视图函数对应的 URL。比如在模板里做链接跳转,或者在重定向时指定目标地址。
硬编码 URL 是最蠢的做法。一旦路由改了,所有硬编码的地方都得跟着改。Flask 提供了 url_for() 函数,可以根据视图函数名动态生成 URL:
from flask import url_for
@app.route('/')
def index():
# 生成 /user/admin 这个路径
user_url = url_for('user_profile', username='admin')
return f'用户主页链接:{user_url}'
@app.route('/user/<username>')
def user_profile(username):
return f'你好,{username}'
你想想看,如果哪天我把 /user/<username> 改成了 /profile/<username>,只要视图函数名不变,url_for 自动就能生成新路径。省心不省心?
url_for 还支持传递额外参数。比如分页场景:
@app.route('/articles')
def article_list():
page = request.args.get('page', 1, type=int)
# 生成 /articles?page=2
next_page_url = url_for('article_list', page=page+1)
return f'下一页链接:{next_page_url}'
四、HTTP 方法:GET、POST 与更多
路由默认只响应 GET 请求。但实际开发中,我们经常需要处理 POST、PUT、DELETE 等请求。比如提交表单用 POST,更新资源用 PUT。
Flask 允许你指定路由支持的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
# 处理登录逻辑...
return f'登录成功,欢迎 {username}'
# GET 请求返回登录页面
return '''
<form method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
'''
同一个路由,根据请求方法不同,执行不同的逻辑。这是 RESTful API 设计的基础。
常用的 HTTP 方法:
- GET:获取资源,幂等,不改变服务器状态
- POST:创建资源,非幂等,常用于表单提交
- PUT:更新资源(全量替换),幂等
- PATCH:部分更新资源
- DELETE:删除资源
五、综合示例:一个简单的博客路由设计
把上面这些知识点串起来,我们设计一个博客系统的路由:
from flask import Flask, url_for, request, redirect
app = Flask(__name__)
# 文章列表(GET)
@app.route('/articles')
def article_list():
page = request.args.get('page', 1, type=int)
return f'文章列表,第 {page} 页'
# 文章详情(GET)
@app.route('/article/<int:article_id>')
def article_detail(article_id):
return f'查看文章 ID:{article_id}'
# 创建文章(GET 显示表单,POST 提交数据)
@app.route('/article/create', methods=['GET', 'POST'])
def create_article():
if request.method == 'POST':
title = request.form.get('title')
content = request.form.get('content')
# 保存到数据库...
# 创建成功后重定向到文章详情页
return redirect(url_for('article_detail', article_id=123))
return '''
<form method="post">
标题:<input type="text" name="title"><br>
内容:<textarea name="content"></textarea><br>
<input type="submit" value="发布">
</form>
'''
# 删除文章(POST 请求,因为删除操作有副作用)
@app.route('/article/<int:article_id>/delete', methods=['POST'])
def delete_article(article_id):
# 执行删除逻辑...
return redirect(url_for('article_list'))
这个例子涵盖了路由定义、动态路由、URL 构建和 HTTP 方法。你仔细看,每个路由的职责都很清晰,URL 设计也符合 RESTful 风格。
- 路由是 URL 到视图函数的映射
- 动态路由用 <变量> 捕获参数,支持类型转换
- url_for 根据视图函数名反查 URL,避免硬编码
- methods 参数控制路由支持的 HTTP 方法
好了,这一章就到这里。下一章我们会深入探讨请求与响应对象——说白了,就是怎么从用户那里拿数据,以及怎么把数据还给用户。到时候见。