1. 请求对象——request
Flask通过全局代理对象request提供所有请求信息。虽然它是“全局”对象,但Flask内部通过线程隔离机制确保每个请求获取的是自己的数据,不会互相干扰。
from flask import Flask, request
app = Flask(__name__)
@app.route("/debug")
def debug():
return f"""
<h1>请求调试信息</h1>
<ul>
<li>方法:{request.method}</li>
<li>路径:{request.path}</li>
<li>完整 URL:{request.url}</li>
<li>主机:{request.host}</li>
<li>客户端 IP:{request.remote_addr}</li>
<li>User-Agent:{request.headers.get('User-Agent')}</li>
</ul>
"""
访问 http://127.0.0.1:5000/debug?foo=bar 即可看到请求的详细信息。
2. 获取查询参数——request.args
URL中?后面的参数称为查询参数(Query String),使用request.args读取,它类似于一个字典。
@app.route("/search")
def search():
keyword = request.args.get("keyword", "")
page = request.args.get("page", "1")
return f"""
<h1>搜索结果</h1>
<p>关键词:{keyword}</p>
<p>页码:{page}</p>
"""
| /search?keyword=flask&page=2 | 关键词:flask,页码:2 |
| /search?keyword=RUNOOB | 关键词:RUNOOB,页码:1(默认值) |
💡 推荐使用.get()方法:request.args.get("key")在key不存在时返回None(或指定的默认值),而直接使用request.args["key"]在key不存在时会抛出KeyError,导致返回400错误页面。
3. 获取表单数据——request.form
处理POST请求提交的表单数据,使用request.form:
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form.get("username", "")
password = request.form.get("password", "")
if not username or not password:
return "<h1>错误</h1><p>用户名和密码不能为空</p>", 400
return f"<h1>注册成功</h1><p>欢迎 {username} 加入 RUNOOB!</p>"
# GET请求时显示注册表单
return """
<h1>注册</h1>
<form method="post">
<p>用户名:<input type="text" name="username"></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="submit" value="注册"></p>
</form>
"""
⚠️ 注意:表单必须设置method="post",否则数据会通过URL查询字符串发送(GET方式),敏感信息会暴露在URL中。
4. 获取JSON数据——request.json
现代Web开发中,JSON是最常见的数据格式。当客户端发送Content-Type: application/json的请求时,使用request.json获取解析后的数据:
@app.post("/api/user")
def create_user():
data = request.json
name = data.get("name", "未知")
email = data.get("email", "未提供")
return {
"message": "用户创建成功",
"name": name,
"email": email
}
用curl测试:
$ curl -X POST http://127.0.0.1:5000/api/user \\
-H "Content-Type: application/json" \\
-d '{"name": "runoob", "email": "test@runoob.com"}'
{
"message": "用户创建成功",
"name": "runoob",
"email": "test@runoob.com"
}
5. 文件上传——request.files
处理上传的文件使用request.files,配合Werkzeug提供的secure_filename()确保文件名安全:
import os
from werkzeug.utils import secure_filename
UPLOAD_DIR = "uploads"
@app.route("/upload", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
if "file" not in request.files:
return "未选择文件", 400
file = request.files["file"]
if file.filename == "":
return "文件名为空", 400
filename = secure_filename(file.filename)
os.makedirs(UPLOAD_DIR, exist_ok=True)
file.save(os.path.join(UPLOAD_DIR, filename))
return f"文件 {filename} 上传成功"
return """
<h1>上传文件</h1>
<form method="post" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="上传"></p>
</form>
"""
| secure_filename() | 过滤路径遍历等危险字符,如../../etc/passwd会被处理为etc_passwd |
| enctype="multipart/form-data" | 表单包含文件上传时必须设置此属性 |
| os.makedirs(…, exist_ok=True) | 确保上传目录存在,exist_ok=True防止目录已存在时报错 |
6. 响应类型完全指南
视图函数可以返回多种类型的数据,Flask会自动将它们转换为合适的HTTP响应。
返回字符串
返回的字符串作为HTML响应体,状态码默认200,Content-Type为text/html。
@app.route("/hello")
def hello():
return "<h1>Hello, World!</h1>"
返回字典或列表(JSON)
自动调用jsonify()转换为JSON响应,Content-Type为application/json。
@app.get("/api/posts")
def get_posts():
return {
"status": "ok",
"data": [
{"id": 1, "title": "Flask 入门教程"},
{"id": 2, "title": "RESTful API 设计"},
]
}
@app.get("/api/tags")
def get_tags():
return ["Python", "Flask", "Web 开发"]
返回元组——控制状态码和响应头
元组有三种组合形式:
# 形式1:(body, status_code)
@app.get("/not-found")
def not_found():
return "<h1>页面不存在</h1>", 404
# 形式2:(body, headers_dict)
@app.get("/custom-header")
def custom_header():
return "OK", {"X-Custom-Header": "runoob"}
# 形式3:(body, status_code, headers_dict)
@app.post("/api/login")
def api_login():
return {"token": "abc123"}, 201, {"X-RateLimit": "100"}
重定向——redirect()
使用redirect()函数将用户引导到另一个URL:
from flask import redirect, url_for
@app.route("/")
def index():
return redirect(url_for("login"))
@app.route("/old-page")
def old_page():
# 永久迁移使用301状态码
return redirect(url_for("new_page"), code=301)
@app.route("/new-page")
def new_page():
return "<h1>这是新页面</h1>"
| 302(默认) | Found | 临时重定向 |
| 303 | See Other | 表单提交后重定向(PRG模式) |
| 301 | Moved Permanently | 永久迁移 |
终止请求——abort()
使用abort()立即终止当前请求并返回HTTP错误:
from flask import abort
@app.route("/post/<int:post_id>")
def view_post(post_id):
if post_id < 1 or post_id > 100:
abort(404)
return f"<h1>文章 #{post_id}</h1>"
@app.route("/admin")
def admin():
abort(403, description="你没有权限访问此页面")
make_response——手动控制响应
当需要手动设置Cookie或自定义响应头时,使用make_response():
from flask import make_response
@app.route("/set-cookie")
def set_cookie():
resp = make_response("<h1>Cookie已设置</h1>")
resp.set_cookie("theme", "dark", max_age=60*60*24) # 有效期24小时
resp.headers["X-Powered-By"] = "RUNOOB-Flask"
return resp
7. request常用属性速查表
| request.method | str | HTTP请求方法 | "GET", "POST" |
| request.path | str | URL路径(不含域名) | "/search" |
| request.url | str | 完整URL | "http://127.0.0.1:5000/search?q=flask" |
| request.args | MultiDict | URL查询参数 | ?keyword=flask&page=1 |
| request.form | MultiDict | POST表单数据 | username=admin |
| request.json | dict或None | JSON请求体(已解析) | {"name": "runoob"} |
| request.files | FileMultiDict | 上传的文件 | request.files["avatar"] |
| request.headers | Headers | 请求头 | request.headers.get("User-Agent") |
| request.cookies | dict | 客户端发来的Cookie | request.cookies.get("theme") |
| request.remote_addr | str | 客户端IP地址 | "127.0.0.1" |
8. 响应类型速查表
| str | return "<h1>Hello</h1>" | HTML响应,200 OK |
| dict | return {"key": "value"} | JSON响应,200 OK |
| list | return ["a", "b"] | JSON响应,200 OK |
| tuple | return "body", 404 | 自定义状态码 |
| tuple | return "body", {"X-Header": "v"} | 自定义响应头 |
| tuple | return "body", 404, {"X-Header": "v"} | 自定义状态码+响应头 |
| Response | return make_response("body") | 完全控制的响应对象 |
| redirect() | return redirect("/login") | 302重定向 |
| abort() | abort(404) | 错误响应 |
小结
本章全面讲解了Flask的请求与响应机制。请求方面,通过request.args读取URL查询参数,request.form读取POST表单数据,request.json解析JSON请求体,request.files处理文件上传,配合secure_filename()确保安全。响应方面,视图函数可返回字符串(HTML)、字典/列表(JSON)、元组(自定义状态码/响应头),还可以通过redirect()实现重定向、abort()终止请求返回错误、make_response()精细控制响应对象。这些知识构成了Flask Web应用数据流转的核心。




