Flask HTTP方法 #
一、HTTP方法概述 #
1.1 常见HTTP方法 #
| 方法 | 用途 | 是否有请求体 |
|---|---|---|
| GET | 获取资源 | 否 |
| POST | 创建资源 | 是 |
| PUT | 完整更新资源 | 是 |
| PATCH | 部分更新资源 | 是 |
| DELETE | 删除资源 | 可选 |
| HEAD | 获取响应头 | 否 |
| OPTIONS | 获取支持的HTTP方法 | 否 |
1.2 RESTful设计原则 #
python
# RESTful风格的URL设计
GET /users # 获取用户列表
GET /users/1 # 获取ID为1的用户
POST /users # 创建新用户
PUT /users/1 # 完整更新ID为1的用户
PATCH /users/1 # 部分更新ID为1的用户
DELETE /users/1 # 删除ID为1的用户
二、指定HTTP方法 #
2.1 单个方法 #
python
@app.route('/users', methods=['GET'])
def get_users():
return '用户列表'
@app.route('/users', methods=['POST'])
def create_user():
return '创建用户'
2.2 多个方法 #
python
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return '处理登录'
return '显示登录表单'
2.3 所有方法 #
python
# 不指定methods,默认只接受GET
@app.route('/page')
def page():
return '页面内容'
# 接受所有方法
@app.route('/api', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def api():
return f'请求方法: {request.method}'
三、GET请求 #
3.1 基本GET请求 #
python
@app.route('/search')
def search():
# 获取查询参数
keyword = request.args.get('q', '')
page = request.args.get('page', 1, type=int)
return f'搜索: {keyword}, 页码: {page}'
# 访问 /search?q=flask&page=2
# 输出: 搜索: flask, 页码: 2
3.2 获取查询参数 #
python
@app.route('/filter')
def filter_items():
# 获取单个参数
category = request.args.get('category')
# 获取参数并设置默认值
sort = request.args.get('sort', 'date')
# 获取参数并转换类型
limit = request.args.get('limit', 10, type=int)
# 获取多个同名参数
tags = request.args.getlist('tag')
# 获取所有参数
all_args = request.args.to_dict()
return {
'category': category,
'sort': sort,
'limit': limit,
'tags': tags,
'all': all_args
}
# 访问 /filter?category=tech&sort=views&limit=20&tag=python&tag=flask
3.3 GET请求示例 #
python
@app.route('/api/users', methods=['GET'])
def get_users():
# 分页参数
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
# 搜索参数
search = request.args.get('search', '')
# 排序参数
sort = request.args.get('sort', 'id')
order = request.args.get('order', 'asc')
# 模拟数据
users = [
{'id': 1, 'name': '张三', 'email': 'zhangsan@example.com'},
{'id': 2, 'name': '李四', 'email': 'lisi@example.com'},
{'id': 3, 'name': '王五', 'email': 'wangwu@example.com'},
]
return jsonify({
'users': users,
'page': page,
'per_page': per_page,
'total': len(users)
})
四、POST请求 #
4.1 表单数据 #
python
@app.route('/submit', methods=['POST'])
def submit():
# 获取表单数据
username = request.form.get('username')
password = request.form.get('password')
return f'用户名: {username}'
# 使用curl测试
# curl -X POST -d "username=admin&password=123456" http://localhost:5000/submit
4.2 JSON数据 #
python
@app.route('/api/users', methods=['POST'])
def create_user():
# 获取JSON数据
data = request.get_json()
if not data:
return jsonify({'error': '无效的JSON数据'}), 400
name = data.get('name')
email = data.get('email')
# 验证必填字段
if not name or not email:
return jsonify({'error': '缺少必填字段'}), 400
# 创建用户逻辑...
return jsonify({
'id': 1,
'name': name,
'email': email
}), 201
# 使用curl测试
# curl -X POST -H "Content-Type: application/json" \
# -d '{"name":"张三","email":"zhangsan@example.com"}' \
# http://localhost:5000/api/users
4.3 文件上传 #
python
import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'error': '没有文件'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': '没有选择文件'}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': '上传成功', 'filename': filename})
return jsonify({'error': '不允许的文件类型'}), 400
五、PUT请求 #
5.1 完整更新 #
python
@app.route('/api/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
data = request.get_json()
# PUT需要提供完整资源
name = data.get('name')
email = data.get('email')
age = data.get('age')
if not all([name, email, age]):
return jsonify({'error': 'PUT请求需要提供完整数据'}), 400
# 更新用户逻辑...
return jsonify({
'id': user_id,
'name': name,
'email': email,
'age': age
})
5.2 PUT vs POST #
python
# POST:创建资源,多次请求会创建多个资源
@app.route('/users', methods=['POST'])
def create_user():
# 每次POST都创建新用户
pass
# PUT:创建或更新资源,多次请求结果相同(幂等)
@app.route('/users/<int:id>', methods=['PUT'])
def create_or_update_user(id):
# 相同请求多次执行,结果相同
pass
六、PATCH请求 #
6.1 部分更新 #
python
@app.route('/api/users/<int:user_id>', methods=['PATCH'])
def patch_user(user_id):
data = request.get_json()
# PATCH只需要提供要更新的字段
updates = {}
if 'name' in data:
updates['name'] = data['name']
if 'email' in data:
updates['email'] = data['email']
if 'age' in data:
updates['age'] = data['age']
if not updates:
return jsonify({'error': '没有要更新的字段'}), 400
# 更新用户逻辑...
return jsonify({
'id': user_id,
'message': '更新成功',
'updated_fields': list(updates.keys())
})
6.2 PUT vs PATCH #
python
# PUT:完整替换
# 原数据: {"name": "张三", "email": "zhang@example.com", "age": 25}
# PUT请求: {"name": "李四", "email": "li@example.com", "age": 30}
# 结果: {"name": "李四", "email": "li@example.com", "age": 30}
# PATCH:部分更新
# 原数据: {"name": "张三", "email": "zhang@example.com", "age": 25}
# PATCH请求: {"name": "李四"}
# 结果: {"name": "李四", "email": "zhang@example.com", "age": 25}
七、DELETE请求 #
7.1 删除资源 #
python
users = {
1: {'id': 1, 'name': '张三'},
2: {'id': 2, 'name': '李四'},
}
@app.route('/api/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
if user_id not in users:
return jsonify({'error': '用户不存在'}), 404
deleted_user = users.pop(user_id)
return jsonify({
'message': '删除成功',
'deleted_user': deleted_user
})
7.2 批量删除 #
python
@app.route('/api/users', methods=['DELETE'])
def delete_users():
data = request.get_json()
ids = data.get('ids', [])
deleted = []
not_found = []
for user_id in ids:
if user_id in users:
deleted.append(users.pop(user_id))
else:
not_found.append(user_id)
return jsonify({
'deleted': deleted,
'not_found': not_found
})
八、其他HTTP方法 #
8.1 HEAD方法 #
python
@app.route('/resource', methods=['HEAD'])
def head_resource():
# 只返回响应头,不返回响应体
response = app.make_response('')
response.headers['Content-Length'] = 1024
response.headers['Content-Type'] = 'application/json'
return response
8.2 OPTIONS方法 #
python
@app.route('/api/users', methods=['OPTIONS'])
def options_users():
response = app.make_response('')
response.headers['Allow'] = 'GET, POST, PUT, DELETE, OPTIONS'
return response
# Flask会自动处理OPTIONS请求(CORS预检)
九、请求方法判断 #
9.1 使用request.method #
python
@app.route('/items', methods=['GET', 'POST', 'PUT', 'DELETE'])
def handle_items():
if request.method == 'GET':
return '获取列表'
elif request.method == 'POST':
return '创建项目'
elif request.method == 'PUT':
return '更新项目'
elif request.method == 'DELETE':
return '删除项目'
9.2 分离路由 #
python
# 推荐:为不同方法定义不同的路由
@app.route('/items', methods=['GET'])
def get_items():
return '获取列表'
@app.route('/items', methods=['POST'])
def create_item():
return '创建项目'
@app.route('/items/<int:id>', methods=['PUT'])
def update_item(id):
return f'更新项目 {id}'
@app.route('/items/<int:id>', methods=['DELETE'])
def delete_item(id):
return f'删除项目 {id}'
十、RESTful API示例 #
10.1 完整CRUD示例 #
python
from flask import Flask, request, jsonify
app = Flask(__name__)
# 模拟数据库
books = {
1: {'id': 1, 'title': 'Python入门', 'author': '张三'},
2: {'id': 2, 'title': 'Flask实战', 'author': '李四'},
}
next_id = 3
# 获取所有书籍
@app.route('/api/books', methods=['GET'])
def get_books():
return jsonify(list(books.values()))
# 获取单本书籍
@app.route('/api/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
book = books.get(book_id)
if book:
return jsonify(book)
return jsonify({'error': '书籍不存在'}), 404
# 创建书籍
@app.route('/api/books', methods=['POST'])
def create_book():
global next_id
data = request.get_json()
if not data or 'title' not in data:
return jsonify({'error': '缺少标题'}), 400
book = {
'id': next_id,
'title': data['title'],
'author': data.get('author', '未知')
}
books[next_id] = book
next_id += 1
return jsonify(book), 201
# 完整更新书籍
@app.route('/api/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
if book_id not in books:
return jsonify({'error': '书籍不存在'}), 404
data = request.get_json()
if not data or 'title' not in data:
return jsonify({'error': '缺少标题'}), 400
books[book_id] = {
'id': book_id,
'title': data['title'],
'author': data.get('author', '未知')
}
return jsonify(books[book_id])
# 部分更新书籍
@app.route('/api/books/<int:book_id>', methods=['PATCH'])
def patch_book(book_id):
if book_id not in books:
return jsonify({'error': '书籍不存在'}), 404
data = request.get_json()
if not data:
return jsonify({'error': '没有更新数据'}), 400
book = books[book_id]
if 'title' in data:
book['title'] = data['title']
if 'author' in data:
book['author'] = data['author']
return jsonify(book)
# 删除书籍
@app.route('/api/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
if book_id not in books:
return jsonify({'error': '书籍不存在'}), 404
deleted = books.pop(book_id)
return jsonify({'message': '删除成功', 'book': deleted})
if __name__ == '__main__':
app.run(debug=True)
十一、最佳实践 #
11.1 HTTP方法选择 #
| 操作 | 方法 | 说明 |
|---|---|---|
| 获取列表 | GET | 无副作用,可缓存 |
| 获取单个 | GET | 无副作用,可缓存 |
| 创建 | POST | 非幂等 |
| 完整更新 | PUT | 幂等,需提供完整数据 |
| 部分更新 | PATCH | 幂等,只需更新字段 |
| 删除 | DELETE | 幂等 |
11.2 状态码使用 #
| 状态码 | 说明 | 使用场景 |
|---|---|---|
| 200 | 成功 | GET、PUT、PATCH、DELETE |
| 201 | 已创建 | POST |
| 204 | 无内容 | DELETE |
| 400 | 错误请求 | 参数错误 |
| 404 | 未找到 | 资源不存在 |
| 405 | 方法不允许 | HTTP方法不支持 |
十二、总结 #
12.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 方法指定 | methods=[‘GET’, ‘POST’] |
| GET | 获取资源,使用request.args |
| POST | 创建资源,使用request.get_json() |
| PUT | 完整更新,幂等 |
| PATCH | 部分更新,幂等 |
| DELETE | 删除资源,幂等 |
12.2 下一步 #
现在你已经掌握了HTTP方法,接下来让我们学习 URL构建,了解如何动态生成URL!
最后更新:2026-03-28