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