一文掌握Python Flask:HTTP微服务开发从入门到部署

Flask是一个轻量级Python Web框架,以其"微内核"设计哲学闻名于世。所谓"微"并非指功能简单,而是指核心简洁、高度可扩展------Flask只提供最基础的Web服务能力,其他所有功能都可通过丰富的扩展生态系统按需添加。这种设计让开发者能够从几行代码的简单应用开始,逐步构建出复杂的企业级系统

一、依赖库的安装与配置

1. 环境准备

首先确保已安装Python(建议版本3.7+),然后通过pip安装Flask依赖:

bash 复制代码
# 安装 Flask
pip install flask
# 如果系统中有多个 Python 版本,可能需要使用 pip3
pip3 install flask

2. 验证安装

安装完成后,创建一个简单的应用来验证 Flask 是否正确安装并正常工作:

python 复制代码
# main.py
# 导入Flask框架,Flask是一个轻量级的Python Web框架  
from flask import Flask  
  
# 创建一个Flask应用程序实例  
# __name__ 参数让Flask知道在哪里查找模板和静态文件等资源  
app = Flask(__name__)  
  
# 使用装饰器定义路由,将URL路径'/'与下面的函数绑定  
# methods参数显式指定只允许GET请求(GET是默认值,这里显式声明更清晰)  
@app.route('/', methods=['GET'])  
def hello():  
    """  
    处理根路径GET请求的处理函数  
    当用户访问网站根路径时,此函数会被调用  
    """    # 返回响应内容,浏览器将显示此字符串  
    return "Flask安装成功!"  
  
if __name__ == '__main__':  
    # 运行Flask应用程序  
    # debug=True 表示开启调试模式:  
    # 1. 代码修改后服务器会自动重启  
    # 2. 发生错误时浏览器会显示详细错误信息  
    # 3. 仅用于开发环境,生产环境应设置为False  
    app.run(debug=True)

运行上述代码后访问 http://127.0.0.1:5000,看到"Flask安装成功!"即表示安装正确。

二、基础HTTP接口实现

掌握 Flask 基础安装后,将学习如何实现常用的 HTTP 接口。涵盖 GET 和 POST 两种最常用的 HTTP 方法。

1. GET 接口

GET 请求用于从服务器获取数据,是最常用的 HTTP 方法。Flask 提供了简洁的路由装饰器语法来处理不同类型的 GET 请求。

1.1 不带参数的 GET 接口

以下举例,演示了最基本的路由定义,不接收任何参数,返回固定的 JSON 数据:

python 复制代码
# main.py
# 导入Flask框架及其必要的组件  
# Flask: 主框架类,用于创建Web应用实例  
# jsonify: 将Python字典转换为JSON格式的HTTP响应  
# request: 用于处理HTTP请求对象,可获取请求参数、头部等信息  
from flask import Flask, jsonify, request  
  
# 创建Flask应用实例  
# __name__ 表示当前模块名,Flask会根据它确定应用根目录,以便查找模板、静态文件等资源  
app = Flask(__name__)  
  
# GET /api/hello  
@app.route('/api/hello', methods=['GET'])  
def hello_world():  
    """  
    最简单的GET接口示例:不接收任何参数,返回固定的欢迎消息。常用于接口连通性测试。  
    """    # 使用jsonify函数创建JSON格式的HTTP响应  
    # 返回一个包含多条信息的字典  
    # 浏览器会自动将JSON数据格式化显示  
    return jsonify({  
        'message': 'Hello, World!',  # 主要消息内容  
        'method': 'GET',  # 请求方法,方便客户端识别  
        'status': 'success'  # 操作状态,常见值:success/error  
    })  
  
if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    app.run(debug=True, port=5000)

使用示例:

  • 访问 http://127.0.0.1:5000/api/hello
1.2 带路径和查询参数的 GET 接口

实际开发中,GET 请求常需要接收参数。Flask 支持两种主要的参数传递方式:路径参数和查询参数。

python 复制代码
# main.py
# 导入Flask框架及其必要的组件  
# Flask: 主框架类,用于创建Web应用实例  
# jsonify: 将Python字典转换为JSON格式的HTTP响应  
# request: 用于处理HTTP请求对象,可获取请求参数、头部等信息  
from flask import Flask, jsonify, request  
  
# 创建Flask应用实例  
# __name__ 表示当前模块名,Flask会根据它确定应用根目录,以便查找模板、静态文件等资源  
app = Flask(__name__)  
  
# GET /api/user/zhangsan?age=25  
@app.route('/api/user/<username>', methods=['GET'])  
def get_user(username):  
    """  
    1. 路径参数:username来自URL路径本身  
    2. 查询参数:age来自URL问号后的查询字符串  
    """    # 从请求的查询字符串中获取'age'参数  
    # request.args 是一个特殊的字典,包含所有查询参数  
    # get() 方法参数说明:  
    #   第一个参数'age': 要获取的参数名  
    #   示例URL: /api/user/zhangsan?age=25  
    age = request.args.get('age', default=18, type=int)  
  
    # 返回JSON格式的响应,包含用户信息  
    # 使用f-string格式化字符串,动态插入变量值  
    return jsonify({  
        'username': username,  # 从路径获取的用户名  
        'age': age,  # 从查询参数获取的年龄  
        'message': f'用户 {username} 的信息',  # 包含用户名的描述信息  
        'method': 'GET',  # 请求方法,方便客户端识别  
        'status': 'success'  # 操作状态,常见值:success/error  
    })
  
if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    app.run(debug=True, port=5000)
  • 访问 http://127.0.0.1:5000/api/user/zhangsan?age=25

2. POST接口

POST 请求用于向服务器提交数据,通常用于创建新资源。

2.1 POST 接口处理 JSON 数据

以下举例展示如何处理 JSON 格式的 POST 请求。

python 复制代码
# main.py
from flask import Flask, jsonify, request

app = Flask(__name__)

# POST http://127.0.0.1:5000/api/user  
# Headers:Content-Type: application/json  
# Body:{"username": "李四", "email": "lisi@example.com"}
@app.route('/api/user', methods=['POST'])  
def create_user():  
    """  
    POST请求特点:  
    1. 请求参数在请求体中,不在URL中显示  
    2. 通常用于创建、修改资源  
    3. 可以传输JSON、表单、文件等多种格式数据  
    """    # 获取JSON格式的请求数据  
    # request.get_json() 方法:  
    # 1. 解析请求体中的JSON数据  
    # 2. 自动转换为Python字典/列表  
    # 3. 如果请求头中Content-Type不是application/json,可设置force=True强制解析  
    data = request.get_json()  
  
    if not data:  
        # 返回错误响应  
        # 200: 成功  
        # 201: 创建成功  
        # 400: 客户端请求错误  
        # 404: 资源不存在  
        # 500: 服务器内部错误  
        return jsonify({'error': '没有提供数据'}), 400  
  
    # 从解析后的JSON数据中获取特定字段  
    username = data.get('username')  # 获取用户名  
    email = data.get('email')        # 获取邮箱  
  
    if not username or not email:  
        # 字段验证失败,返回400错误  
        return jsonify({'error': '用户名和邮箱是必填项'}), 400  
  
    # 创建用户数据(模拟数据库操作)  
    # 在实际应用中,这里应该:  
    # 1. 连接数据库  
    # 2. 检查用户名/邮箱是否已存在  
    # 3. 将数据插入数据库  
    # 4. 获取数据库生成的自增ID  
    user_data = {  
        'id': 1,  # 模拟数据库自增ID,实际应从数据库获取  
        'username': username,  # 用户输入的用户名  
        'email': email,        # 用户输入的邮箱  
        'created_at': '2024-01-01'  # 创建时间,实际应从数据库获取或使用当前时间  
    }  
  
    # 返回成功响应  
    # HTTP状态码 201: Created,表示资源创建成功  
    # 与200的区别:201明确表示创建了新的资源  
    return jsonify({  
        'message': '用户创建成功',  # 操作成功消息  
        'user': user_data,        # 创建的完整用户信息  
        'method': 'POST',         # 请求方法,便于客户端识别  
        'status': 'success'       # 操作状态  
    }), 201

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    app.run(debug=True, port=5000)

使用 Postman 测试:

bash 复制代码
POST http://127.0.0.1:5000/api/user  
Headers:Content-Type: application/json  
Body:{"username": "李四", "email": "lisi@example.com"}
2.2 POST 接口处理表单请求

除了 JSON 格式,表单提交是另一种常见的 POST 请求方式,常用于文本表单提交和文件上传。

python 复制代码
# main.py
from flask import Flask, jsonify, request

app = Flask(__name__)

# 提交纯文本表单:
# POST /api/form/user HTTP/1.1
# Content-Type: application/x-www-form-urlencoded
# username=lisi&email=lisi@example.com
@app.route('/api/form/user', methods=['POST'])
def create_user_form():
    """
    通用表单处理接口,支持两种格式
    """
    # 获取Content-Type
    content_type = request.headers.get('Content-Type', '').lower()

    # 检查是否支持的表单格式
    is_form_urlencoded = 'application/x-www-form-urlencoded' in content_type
    is_form_data = 'multipart/form-data' in content_type
    if not (is_form_urlencoded or is_form_data):
        return jsonify({
            'error': '不支持的Content-Type',
            'supported_types': [
                'application/x-www-form-urlencoded',
                'multipart/form-data'
            ]
        }), 415

    """
    POST表单请求特点:
    1. 数据通过表单字段(form data)传递,而不是JSON
    2. Content-Type通常为application/x-www-form-urlencoded或multipart/form-data
    3. 适合HTML表单提交、文件上传等场景
    4. 数据在请求体中,格式为key1=value1&key2=value2
    """
    # 获取表单数据(两种格式都可以通过request.form获取)
    username = request.form.get('username')
    email = request.form.get('email')

    # 验证必填字段
    if not username or username.strip() == '':
        return jsonify({'error': '用户名是必填项'}), 400
    if not email or email.strip() == '':
        return jsonify({'error': '邮箱是必填项'}), 400

    # 处理文件上传(仅form-data格式)
    uploaded_files = {}
    if is_form_data:
        for filename, file in request.files.items():
            if file and file.filename:
                # 这里可以保存文件
                file.save(f'uploads/{file.filename}')
                uploaded_files[filename] = {
                    'filename': file.filename,
                    'content_type': file.content_type,
                    'size': len(file.read())
                }
                file.seek(0)  # 重置文件指针

    # 创建用户数据(模拟数据库操作)
    user_data = {
        'id': 1,
        'username': username.strip(),
        'email': email.strip(),
        'created_at': '2024-01-01',
        'format': 'form-data' if is_form_data else 'x-www-form-urlencoded',
        'uploaded_files': uploaded_files
    }
    # 返回成功响应:201 Created状态码
    return jsonify({
        'message': '用户创建成功',
        'user': user_data,
        'method': 'POST',
        'status': 'success'
    }), 201

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    app.run(debug=True, port=5000)

使用 Postman 测试:

bash 复制代码
POST http://127.0.0.1:5000/api/form/user
Headers:Content-Type: application/x-www-form-urlencoded
Body:username=lisi&email=lisi@example.com

使用 Postman 测试:

bash 复制代码
POST http://127.0.0.1:5000/api/form/user
Content-Type: multipart/form-data; boundary=4235013262151947840

----4235013262151947840
Content-Disposition: form-data; name="username"
lisi
----4235013262151947840
Content-Disposition: form-data; name="email"
lisi@example.com
----4235013262151947840
Content-Disposition: form-data; name=""; filename="WX20240906-100536.png"
Content-Type: image/png

WX20240906-100536.png字节流数据
----4235013262151947840

三、数据库集成

现代Web应用开发中,数据库是不可或缺的核心组件。Flask作为一款轻量级Web框架,虽然自身不包含数据库功能,但通过其出色的扩展机制,可以轻松集成多种数据库系统。数据库集成主要涉及两个方面:数据模型的建立数据的持久化存储

1. 数据库配置与模型定义

Flask支持多种数据库系统,包括:

  • SQLite:轻量级文件数据库,适合小型应用和快速原型开发
  • MySQL:成熟的关系型数据库,适合中型到大型应用

本示例使用SQLite,因为它无需单独安装数据库服务器,且数据存储在单一文件中,便于开发和测试。

python 复制代码
from flask import Flask, jsonify, request  
from flask_sqlalchemy import SQLAlchemy  
from datetime import datetime  
  
# 创建Flask应用实例  
# __name__ 表示当前模块名,Flask会根据它确定应用根目录,以便查找模板、静态文件等资源  
flaskApp = Flask(__name__)  
  
# 设置SQLite数据库的URI,数据库文件将保存在项目根目录下的users.db文件中  
# 'sqlite:///' 表示使用SQLite数据库,'users.db'是数据库文件名  
flaskApp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'  
# 关闭SQLAlchemy的修改追踪功能:设置为False可以节省内存,避免性能警告  
flaskApp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  
  
# 创建SQLAlchemy实例,将其绑定到Flask应用:这个实例将用于所有数据库操作  
sqliteDb = SQLAlchemy(flaskApp)  
  
  
# 定义数据模型(User类):继承自db.Model,表示这是一个数据库模型  
class User(sqliteDb.Model):  
    # 定义id字段:整型,主键,自动递增  
    id = sqliteDb.Column(sqliteDb.Integer, primary_key=True)  
    # 定义username字段:字符串类型,最大长度80字符  
    # unique=True 表示用户名必须唯一  
    # nullable=False 表示该字段不能为空  
    username = sqliteDb.Column(sqliteDb.String(80), unique=True, nullable=False)  
    # 定义email字段:字符串类型,最大长度120字符  
    # unique=True 表示邮箱必须唯一  
    # nullable=False 表示该字段不能为空  
    email = sqliteDb.Column(sqliteDb.String(120), unique=True, nullable=False)  
    # 定义created_at字段:日期时间类型  
    # default=datetime.utcnow 表示默认值为当前UTC时间  
    # 当创建新用户记录时,如果未指定创建时间,会自动使用当前时间  
    created_at = sqliteDb.Column(sqliteDb.DateTime, default=datetime.utcnow)  
  
    # 定义实例方法,将User对象转换为字典格式  
    # 用于API响应,便于序列化为JSON格式  
    def to_dict(self):  
        return {  
            'id': self.id,  
            'username': self.username,  
            'email': self.email,  
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')  
        }  
  
  
# 创建数据库表:使用应用上下文管理器,确保在正确的应用上下文中执行数据库操作  
with flaskApp.app_context():  
    # 根据定义的数据模型创建所有数据库表:如果表已存在,不会重复创建  
    sqliteDb.create_all()

2. 创建用户

Create, Read, Update, Delete是任何数据驱动应用的基本操作。创建(Create)操作允许系统添加新数据记录,是实现数据持久化的第一步。

python 复制代码
# 创建新资源的接口  
# 与获取列表的路径相同,但使用POST方法  
# RESTful设计:同一路径不同方法执行不同操作  
@flaskApp.route('/api/create/user', methods=['POST'])  
def create_user():  
    """  
    创建新用户  
    RESTful风格:POST /api/users 创建新资源  
    请求体应包含JSON格式的用户数据  
    """    # 获取JSON格式的请求数据  
    # request.get_json() 解析请求体中的JSON,返回Python字典  
    data = request.get_json()  
  
    # 验证必要字段  
    # 定义必须提供的字段列表  
    required_fields = ['username', 'email']  
    # 遍历每个必需字段  
    for field in required_fields:  
        # 检查字段是否存在且值不为空(去除空格后)  
        # data[field] 直接访问字典,如果field不存在会引发KeyError  
        # 更好的写法是:if field not in data or not data.get(field, '').strip()  
        if field not in data or not data[field].strip():  
            # 返回400 Bad Request错误  
            # 提供具体的错误信息,指出哪个字段缺失  
            return jsonify({'error': f'{field}是必填项'}), 400  
  
    # 检查用户名是否已存在(唯一性验证)  
    # User.query.filter_by(username=data['username']) 创建查询条件  
    # .first() 执行查询并返回第一个结果,没有结果则返回None  
    if User.query.filter_by(username=data['username']).first():  
        # 返回409 Conflict错误  
        # 409表示请求与服务器当前状态冲突(用户名已存在)  
        return jsonify({'error': '用户名已存在'}), 409  
  
    # 检查邮箱是否已存在(唯一性验证)  
    if User.query.filter_by(email=data['email']).first():  
        # 同样返回409冲突错误  
        return jsonify({'error': '邮箱已存在'}), 409  
  
    # 创建新用户对象实例  
    # User 是SQLAlchemy模型类  
    # 通过关键字参数传递字段值  
    new_user = User(  
        username=data['username'],  # 从请求数据获取用户名  
        email=data['email']  # 从请求数据获取邮箱  
    )  
  
    # 将新用户对象添加到数据库会话  
    # sqliteDb.session.add() 将对象标记为"待添加"  
    sqliteDb.session.add(new_user)  
    # 提交会话,将更改保存到数据库  
    # 执行INSERT语句  
    sqliteDb.session.commit()  
  
    # 返回201 Created状态码  
    # 201表示资源创建成功,通常包含新创建的资源信息  
    return jsonify({  
        'message': '用户创建成功',  # 成功消息  
        'user': new_user.to_dict()  # 返回新用户的完整信息  
    }), 201

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)

使用 Postman 测试:

3. 返回所有用户

当用户数量较多时,直接返回所有用户可能导致性能问题。实际应用中应考虑:

python 复制代码
# 使用装饰器定义路由,将URL路径与处理函数绑定  
# '/api/users' 是接口的URL路径  
# methods=['GET'] 指定此路由只响应GET请求  
# GET请求用于获取资源列表,不会修改服务器状态  
@flaskApp.route('/api/users', methods=['GET'])  
def get_all_users():  
    """  
    获取所有用户信息  
    RESTful风格:GET /api/users 获取资源列表  
    无需参数,返回用户数组  
    """    # 执行数据库查询,获取User表中的所有记录  
    # User.query.all() 返回一个包含所有用户对象的列表  
    # 如果表中没有用户,返回空列表 []    users = User.query.all()  
  
    # 返回JSON格式的响应  
    # 使用列表推导式将每个用户对象转换为字典  
    # user.to_dict() 是User模型类中定义的方法,将对象序列化为字典  
    return jsonify({  
        'users': [user.to_dict() for user in users],  # 用户列表  
        'count': len(users)  # 用户总数,便于前端分页统计  
    })

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)

使用 Postman 测试:

4. 返回单个用户

RESTful API通过URL路径参数定位具体资源。这种方式:

  1. 语义清晰,符合REST设计原则
  2. 便于缓存和代理处理
  3. 支持层级化资源访问
python 复制代码
# 定义带路径参数的路由  
# '<int:user_id>' 是路径参数,int: 指定参数类型为整数  
# 访问时URL中的数字部分会被捕获并传递给user_id参数  
# 例如:/api/users/123 中的123会作为user_id参数  
@flaskApp.route('/api/users/<int:user_id>', methods=['GET'])  
def get_user(user_id):  
    """  
    获取单个用户详细信息  
    RESTful风格:GET /api/users/{id} 获取指定资源  
    user_id: 用户ID,从URL路径中获取  
    """    # 根据主键(id)查询用户  
    # User.query.get(user_id) 相当于 SELECT * FROM user WHERE id = user_id    # 如果找不到用户,返回None  
    user = User.query.get(user_id)  
  
    # 检查用户是否存在  
    # 如果user是None,表示数据库中不存在该ID的用户  
    if user is None:  
        # 返回404 Not Found错误  
        # 404状态码表示请求的资源不存在  
        return jsonify({'error': '用户不存在'}), 404  
  
    # 用户存在,返回其信息  
    # 调用to_dict()方法将用户对象转换为字典  
    return jsonify(user.to_dict())

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)

使用 Postman 测试:

5. 搜索用户

搜索是用户界面的核心功能之一,举例如下:

python 复制代码
# 搜索用户接口  
# 使用GET方法,通过查询参数传递搜索条件  
# RESTful风格:GET /api/users/search?username=xxx&email=xxx  
@flaskApp.route('/api/users/search', methods=['GET'])  
def search_users():  
    """  
    搜索用户  
    通过查询参数过滤用户列表    支持模糊搜索  
    """    # 从URL查询字符串获取搜索参数  
    # request.args 包含所有查询参数  
    # get() 方法:第一个参数是参数名,第二个参数是默认值  
    username = request.args.get('username', '')  # 用户名搜索关键词  
    email = request.args.get('email', '')  # 邮箱搜索关键词  
  
    # 创建基础查询  
    # User.query 返回一个查询对象,可以链式调用过滤方法  
    query = User.query  
  
    # 如果提供了用户名搜索条件  
    if username:  
        # 添加用户名过滤条件  
        # contains() 方法实现模糊搜索,SQL中的LIKE '%username%'  
        query = query.filter(User.username.contains(username))  
  
    # 如果提供了邮箱搜索条件  
    if email:  
        # 添加邮箱过滤条件  
        query = query.filter(User.email.contains(email))  
  
    # 执行查询,获取结果列表  
    # query.all() 执行构建好的查询  
    users = query.all()  
  
    # 返回搜索结果  
    return jsonify({  
        'users': [user.to_dict() for user in users],  # 搜索结果列表  
        'count': len(users),  # 结果数量  
        'search_params': {  # 返回搜索参数,便于前端确认  
            'username': username,  
            'email': email  
        }  
    })

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)

使用 Postman 测试:

5. 更新用户信息

以下示例实现的是PUT语义更新客户端提供的字段。

python 复制代码
# 更新现有资源的接口  
# 使用PUT方法,需要指定要更新的资源ID  
# RESTful设计:PUT用于完全替换资源  
@flaskApp.route('/api/users/<int:user_id>', methods=['PUT'])  
def update_user(user_id):  
    """  
    更新用户信息  
    RESTful风格:PUT /api/users/{id} 更新指定资源  
    PUT通常用于完全替换资源,PATCH用于部分更新  
    """   
	# 先查询要更新的用户是否存在  
    user = User.query.get(user_id)  
    if user is None:  
        return jsonify({'error': '用户不存在'}), 404  
  
    # 获取请求中的更新数据  
    data = request.get_json()  
  
    # 更新用户名(如果提供了新用户名)  
    # 检查'username'字段是否存在且值不为空  
    if 'username' in data and data['username']:  
        # 检查新用户名是否与其他用户冲突(排除当前用户自己)  
        # User.query.filter() 创建复杂查询条件  
        # User.username == data['username']: 用户名等于新用户名  
        # User.id != user_id: 排除当前用户自己  
        # .first(): 获取第一个匹配的用户  
        existing_user = User.query.filter(  
            User.username == data['username'],  # 用户名相等  
            User.id != user_id  # ID不等于当前用户ID  
        ).first()  
        # 如果找到其他用户使用这个用户名  
        if existing_user:  
            return jsonify({'error': '用户名已被使用'}), 409  
        # 更新用户名  
        user.username = data['username']  
  
    # 更新邮箱(如果提供了新邮箱)  
    if 'email' in data and data['email']:  
        # 检查新邮箱是否与其他用户冲突  
        existing_user = User.query.filter(  
            User.email == data['email'],  # 邮箱相等  
            User.id != user_id  # ID不等于当前用户ID  
        ).first()  
        if existing_user:  
            return jsonify({'error': '邮箱已被使用'}), 409  
        # 更新邮箱  
        user.email = data['email']  
  
    # 提交更改到数据库  
    # 执行UPDATE语句  
    sqliteDb.session.commit()  
  
    # 返回更新后的用户信息  
    return jsonify({  
        'message': '用户更新成功',  
        'user': user.to_dict()  # 返回更新后的用户信息  
    })

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)

使用 Postman 测试:

6. 删除用户

删除操作需要谨慎处理:

python 复制代码
# 删除资源的接口  
# 使用DELETE方法  
# RESTful设计:DELETE用于删除资源  
@flaskApp.route('/api/users/<int:user_id>', methods=['DELETE'])  
def delete_user(user_id):  
    """  
    删除用户  
    RESTful风格:DELETE /api/users/{id} 删除指定资源  
    删除后资源将不可恢复  
    """    # 查询要删除的用户  
    user = User.query.get(user_id)  
    if user is None:  
        return jsonify({'error': '用户不存在'}), 404  
  
    # 从数据库会话中标记用户为待删除  
    sqliteDb.session.delete(user)  
    # 提交更改,执行DELETE语句  
    sqliteDb.session.commit()  
  
    # 返回200 OK状态码  
    # 204 No Content也可以,但这里返回了消息体  
    return jsonify({'message': '用户删除成功'}), 200

if __name__ == '__main__':  
    # 参数说明:  
    #   debug=True: 启用调试模式  
    #     优点:1. 代码修改后自动重启服务  
    #          2. 出错时显示详细错误信息  
    #          3. 显示交互式调试器(仅本地访问)  
    #     注意:生产环境必须设为False  
    #   port=5000: 指定服务运行的端口号  
    flaskApp.run(debug=True, port=5000)
相关推荐
SunnyRivers2 小时前
Python 中的 HTTP 客户端:Requests、HTTPX 与 AIOHTTP 对比
python·httpx·requests·aiohttp·区别
u0109272713 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
lixin5565563 小时前
基于迁移学习的图像风格增强器
java·人工智能·pytorch·python·深度学习·语言模型
阡陌..3 小时前
浅谈SAR图像处理---形态学滤波
图像处理·人工智能·python
猿小羽3 小时前
OkHttp vs Retrofit 技术分析报告 - 1769404939594
http·okhttp·retrofit·csdn
qq_229058014 小时前
python-Dgango项目收集静态文件、构建前端、安装依赖
开发语言·python
测试人社区—66794 小时前
2025区块链分层防御指南:AI驱动的安全测试实战策略
开发语言·驱动开发·python·appium·pytest
m0_748248654 小时前
C++使用HTTP库和框架轻松发送HTTP请求
开发语言·c++·http
喵手4 小时前
Python爬虫零基础入门【第九章:实战项目教学·第10节】下载型资源采集:PDF/附件下载 + 去重校验!
爬虫·python·爬虫实战·python爬虫工程化实战·零基础python爬虫教学·下载型资源采集·pdf下载