实战教程:使用Python和Flask构建一个简单的REST API

前言
在现代的Web和移动应用开发中,REST API (Representational State Transfer Application Programming Interface) 扮演着至关重要的角色。它是一种架构风格,定义了一组用于创建网络服务的约束。通过API,不同的应用程序(例如,一个前端网站和一个后端服务器)可以相互通信。
Python拥有众多优秀的Web框架,其中 Flask 以其轻量、灵活和易于上手的特点,成为构建API和Web应用的热门选择。 [6]
本教程将手把手带你使用Python和Flask,从零开始构建一个简单的书店REST API。你将学会如何处理不同的HTTP请求(GET, POST, PUT, DELETE),并创建一个功能完备的CRUD(创建、读取、更新、删除)服务。
准备工作
在开始之前,请确保你的电脑上已经安装了以下软件:
- Python 3: 你可以从 Python官网 下载并安装。
- 代码编辑器: 例如 VS Code, Sublime Text, 或者 PyCharm。
- 命令行工具: 如 Windows的CMD/PowerShell 或 macOS/Linux的Terminal。
- (可选) API测试工具: 如 Postman 或 Insomnia。我们也会提供使用
curl
的命令行测试方法。
第一步:搭建项目环境
一个良好的项目结构和隔离的开发环境是成功的开始。
创建项目文件夹
打开你的命令行工具,创建一个新的项目文件夹并进入该目录。
mkdir flask-book-api
cd flask-book-api
创建并激活虚拟环境
使用虚拟环境可以确保项目的依赖与全局Python环境隔离,避免版本冲突。
# For macOS/Linux
python3 -m venv venv
source venv/bin/activate
# For Windows
python -m venv venv
.\venv\Scripts\activate
激活成功后,你会在命令行提示符前看到 (venv)
的字样。
安装Flask
在激活的虚拟环境中,使用pip安装Flask。
pip install Flask
第二步:你的第一个Flask应用
让我们从一个经典的 "Hello, World!" 开始,以确保Flask已经正确安装。
- 在
flask-book-api
文件夹中,创建一个名为 app.py
的文件。 在 app.py
中输入以下代码:
from flask import Flask
# 创建一个Flask应用实例
app = Flask(__name__)
# 定义一个路由和视图函数
@app.route('/')
def hello_world():
return 'Hello, World!'
# 确保直接运行时才启动服务器
if __name__ == '__main__':
app.run(debug=True)
app = Flask(__name__)
:创建了Flask应用的一个实例。@app.route('/')
:这是一个装饰器,它告诉Flask哪个URL应该触发我们的函数。/
是网站的根路径。app.run(debug=True)
:启动开发服务器。debug=True
会在代码修改后自动重启服务器,并提供详细的错误信息。
运行应用
在命令行中运行以下命令:
python app.py
你应该会看到类似以下的输出:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* ...
现在,打开浏览器并访问 http://127.0.0.1:5000/
,你将看到 "Hello, World!" 的字样。
第三步:设计我们的REST API
我们的书店API需要处理关于“书籍”的资源。我们将定义以下几个API端点(Endpoints)来操作书籍数据。为了简化,我们暂时将数据存储在内存的一个列表中。
HTTP 方法 | URL 端点 | 动作 |
---|
GET | /books | 获取所有书籍的列表 |
GET | /books/<int:book_id> | 获取指定ID的书籍信息 |
POST | /books | 添加一本新书 |
PUT | /books/<int:book_id> | 更新指定ID的书籍信息 |
DELETE | /books/<int:book_id> | 删除指定ID的书籍 |
第四步:实现API功能
现在,让我们来修改 app.py
文件,实现完整的CRUD功能。
用以下代码替换 app.py
的全部内容:
from flask import Flask, jsonify, request
app = Flask(__name__)
# 使用内存数据库(一个字典列表)
books = [
{'id': 1, 'title': 'The Lord of the Rings', 'author': 'J.R.R. Tolkien'},
{'id': 2, 'title': 'Pride and Prejudice', 'author': 'Jane Austen'}
]
next_book_id = 3
# GET /books - 获取所有书籍
@app.route('/books', methods=['GET'])
def get_books():
return jsonify({'books': books})
# GET /books/<id> - 获取指定书籍
@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
book = next((book for book in books if book['id'] == book_id), None)
if book:
return jsonify({'book': book})
return jsonify({'message': 'Book not found'}), 404
# POST /books - 添加新书
@app.route('/books', methods=['POST'])
def add_book():
global next_book_id
if not request.json or not 'title' in request.json or not 'author' in request.json:
return jsonify({'message': 'Bad request, title and author are required'}), 400
new_book = {
'id': next_book_id,
'title': request.json['title'],
'author': request.json['author']
}
books.append(new_book)
next_book_id += 1
return jsonify({'book': new_book}), 201
# PUT /books/<id> - 更新书籍信息
@app.route('/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
book = next((book for book in books if book['id'] == book_id), None)
if not book:
return jsonify({'message': 'Book not found'}), 404
if not request.json:
return jsonify({'message': 'Bad request'}), 400
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
return jsonify({'book': book})
# DELETE /books/<id> - 删除书籍
@app.route('/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
global books
book = next((book for book in books if book['id'] == book_id), None)
if not book:
return jsonify({'message': 'Book not found'}), 404
books = [b for b in books if b['id'] != book_id]
return jsonify({'message': 'Book deleted successfully'})
if __name__ == '__main__':
app.run(debug=True)
代码解释:
jsonify
: 这是一个Flask函数,可以将Python字典转换为JSON格式的响应,并自动设置正确的 Content-Type
头 (application/json
)。 [7]request
: 从 flask
导入,用于访问传入的请求数据,例如 request.json
可以获取POST或PUT请求中的JSON数据。 [10]methods=['GET', 'POST']
: 默认情况下,路由只响应GET请求。要处理其他HTTP方法,需要在 @app.route()
装饰器中指定。 [11]- 状态码: 我们返回了不同的HTTP状态码来表示请求的结果,如
201 Created
表示资源创建成功,404 Not Found
表示资源未找到。
第五步:测试你的API
确保你的 app.py
仍在运行。现在,打开一个新的命令行窗口(不要关闭正在运行Flask的那个),我们将使用 curl
来测试我们的API。
获取所有书籍 (GET)
curl http://127.0.0.1:5000/books
响应:
{
"books": [
{
"author": "J.R.R. Tolkien",
"id": 1,
"title": "The Lord of the Rings"
},
{
"author": "Jane Austen",
"id": 2,
"title": "Pride and Prejudice"
}
]
}
添加一本新书 (POST)
curl -X POST -H "Content-Type: application/json" -d '{"title": "1984", "author": "George Orwell"}' http://127.0.0.1:5000/books
响应:
{
"book": {
"author": "George Orwell",
"id": 3,
"title": "1984"
}
}
获取指定ID的书籍 (GET)
curl http://127.0.0.1:5000/books/3
响应:
{
"book": {
"author": "George Orwell",
"id": 3,
"title": "1984"
}
}
更新书籍信息 (PUT)
curl -X PUT -H "Content-Type: application/json" -d '{"title": "Nineteen Eighty-Four"}' http://127.0.0.1:5000/books/3
响应:
{
"book": {
"author": "George Orwell",
"id": 3,
"title": "Nineteen Eighty-Four"
}
}
删除书籍 (DELETE)
curl -X DELETE http://127.0.0.1:5000/books/3
响应:
{
"message": "Book deleted successfully"
}
总结
恭喜你!你已经成功使用Python和Flask构建并测试了一个功能完整的REST API。
在本教程中,你学习了:
- 如何设置一个基本的Flask项目。
- 如何定义路由并处理不同的HTTP方法。
- 如何使用
jsonify
返回JSON数据。 - 如何使用
request
处理传入的JSON数据。 - 如何实现一个完整的CRUD(创建、读取、更新、删除)服务。
这只是一个开始。从这里出发,你可以继续探索更高级的主题,例如:
- 数据库集成: 用SQLite, PostgreSQL等真实数据库替换内存数据。
- 数据校验: 使用 Marshmallow 等库来验证和序列化数据。
- 认证与授权: 添加用户登录和权限控制。
- 蓝图 (Blueprints): 组织更大型的Flask应用。
希望本教程能为你的Web开发之旅提供一个坚实的起点!
、