杰瑞科技汇

Python RESTful 文档如何快速上手?

目录

  1. 什么是 RESTful API?
  2. Python RESTful API 开发框架
    • Flask
    • Django REST framework (DRF)
    • FastAPI
  3. 核心概念与最佳实践
    • HTTP 方法
    • URL 设计 (URI)
    • 状态码
    • 数据格式
    • 认证与授权
    • 版本控制
    • 异常处理
  4. 完整代码示例
    • 使用 Flask + Flask-RESTx
    • 使用 FastAPI
  5. API 文档自动化
    • Swagger / OpenAPI
    • ReDoc
  6. 进阶主题
    • 数据库集成
    • 测试
    • 部署

什么是 RESTful API?

REST (Representational State Transfer,表述性状态转移) 是一种软件架构风格,而不是一个标准,它使用 HTTP 协议来创建、读取、更新和删除资源。

RESTful API 的核心思想是将数据视为“资源”,并通过标准的 HTTP 方法对这些资源进行操作。

RESTful 的关键特征:

  • 无状态: 服务器不保存客户端的状态,每个请求都包含处理该请求所需的所有信息。
  • 面向资源: URL 唯一标识一个资源,/users, /products/123
  • 使用标准 HTTP 方法:
    • GET: 获取资源。
    • POST: 创建新资源。
    • PUT: 更新整个资源(幂等)。
    • PATCH: 部分更新资源(非幂等)。
    • DELETE: 删除资源。
  • 使用标准 HTTP 状态码: 200 OK, 201 Created, 404 Not Found, 500 Internal Server Error
  • 数据格式: 通常使用 JSON 或 XML,JSON 是目前最主流的选择。

Python RESTful API 开发框架

Python 生态中有多个优秀的框架用于构建 RESTful API。

a. Flask

Flask 是一个轻量级的“微框架”,非常灵活,适合小型项目或作为更大应用的一部分。

  • 优点: 简单、易学、高度可扩展。
  • 缺点: 对于大型项目,需要自己组合很多组件(如 ORM、认证等)。
  • 核心库: Flask
  • 推荐扩展:
    • Flask-RESTx: 提供了创建 REST API 的工具,自动生成交互式 Swagger UI 文档,比 Flask-RESTful 更现代。
    • Flask-SQLAlchemy: ORM,用于数据库操作。
    • Flask-JWT-Extended: 用于处理 JWT 认证。

b. Django REST framework (DRF)

DRF 是基于 Django 框架构建的强大、灵活的工具集,它为 Django 提供了构建 RESTful API 的能力。

  • 优点: 功能全面、文档完善、内置强大的序列化器、权限控制和认证系统。
  • 缺点: 学习曲线较陡,对于非常简单的项目可能显得有些“重”。
  • 核心库: djangorestframework

c. FastAPI

FastAPI 是一个现代、快速的(高性能) Web 框架,用于构建 API,它基于 Python 3.6+ 的类型提示。

  • 优点: 性能极高(与 Node.js 和 Go 相当)、自动生成 OpenAPI 文档、内置数据验证(使用 Pydantic)、易于学习和使用。
  • 缺点: 相对较新,但社区发展非常迅速。
  • 核心特性: 自动交互式 API 文档(Swagger UI 和 ReDoc)、依赖注入系统。

核心概念与最佳实践

HTTP 方法

方法 行为 幂等性 安全性
GET 读取资源
POST 创建资源
PUT 替换整个资源
PATCH 部分更新资源
DELETE 删除资源

幂等性:多次执行同一操作,结果与执行一次相同。GETDELETE 通常是幂等的。

URL 设计

  • 使用名词复数形式表示资源集合:/users, /products
  • 使用嵌套表示资源间的关系:/users/123/orders (用户123的所有订单)。
  • 使用查询参数进行过滤、排序和分页:/products?category=books&sort=price&page=2

状态码

  • 2xx (成功): 200 OK, 201 Created, 204 No Content (成功但无返回内容)
  • 4xx (客户端错误): 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed
  • 5xx (服务器错误): 500 Internal Server Error

数据格式

JSON (JavaScript Object Notation) 是事实上的标准。

请求示例 (POST):

{
  "name": "John Doe",
  "email": "john.doe@example.com"
}

响应示例 (GET /users/123):

{
  "id": 123,
  "name": "John Doe",
  "email": "john.doe@example.com"
}

认证与授权

  • 认证: 确认用户身份是谁,常用方法有 API Key、JWT (JSON Web Token)。
  • 授权: 确认用户是否有权限执行某个操作。

版本控制

当 API 发生重大变更时,需要进行版本控制,以避免破坏现有客户端。

  • URL 路径: /api/v1/users
  • 查询参数: ?version=v1
  • 请求头: Accept: application/vnd.company.v1+json

完整代码示例

我们将创建一个简单的 "Todo List" API。

a. 使用 Flask + Flask-RESTx

安装依赖

pip install flask flask-restx

创建 app.py

from flask import Flask
from flask_restx import Api, Resource, fields, reqparse
app = Flask(__name__)
api = Api(app, version='1.0', title='TodoMVC API', description='A simple TodoMVC API')
# 定义命名空间,使 API 更有组织
ns = api.namespace('todos', description='Todo operations')
# 定义数据模型,用于文档生成和验证
todo_model = api.model('Todo', {
    'id': fields.Integer(required=True, description='Todo task unique identifier'),
    'task': fields.String(required=True, description='The task details'),
    'done': fields.Boolean(required=False, description='Indicates if the task is done'),
})
# 模拟数据库
todos = {}
todo_id_counter = 1
# 请求解析器,用于验证和解析请求数据
parser = reqparse.RequestParser()
parser.add_argument('task', type=str, required=True, help='Task cannot be blank!')
@ns.route('/')
class TodoList(Resource):
    @ns.marshal_list_with(todo_model) # 使用模型序列化响应
    def get(self):
        """列出所有待办事项"""
        return list(todos.values())
    @ns.expect(parser) # 期望请求数据符合 parser 的定义
    @ns.marshal_with(todo_model, code=201) # 序列化响应,并返回 201 状态码
    def post(self):
        """创建一个新的待办事项"""
        global todo_id_counter
        args = parser.parse_args()
        todo = {'id': todo_id_counter, 'task': args['task'], 'done': False}
        todos[todo_id_counter] = todo
        todo_id_counter += 1
        return todo, 201
@ns.route('/<int:todo_id>')
@ns.response(404, 'Todo not found')
@ns.param('todo_id', 'The task identifier')
class Todo(Resource):
    @ns.marshal_with(todo_model)
    def get(self, todo_id):
        """获取单个待办事项"""
        todo = todos.get(todo_id)
        if not todo:
            api.abort(404, "Todo not found")
        return todo
    @ns.expect(parser)
    @ns.marshal_with(todo_model)
    def put(self, todo_id):
        """更新一个待办事项"""
        args = parser.parse_args()
        todo = todos.get(todo_id)
        if not todo:
            api.abort(404, "Todo not found")
        todo['task'] = args['task']
        return todo
    def delete(self, todo_id):
        """删除一个待办事项"""
        if todo_id not in todos:
            api.abort(404, "Todo not found")
        del todos[todo_id]
        return '', 204 # No Content
if __name__ == '__main__':
    app.run(debug=True)

运行并访问文档

python app.py

然后打开浏览器访问 http://127.0.0.1:5000/,你会看到一个 Swagger UI 界面,可以直接测试你的 API。

b. 使用 FastAPI

安装依赖

pip install fastapi "uvicorn[standard]"

创建 main.py

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI("TodoMVC API",
    description="A simple TodoMVC API with FastAPI",
    version="1.0.0"
)
# Pydantic 模型,用于数据验证和序列化
class Todo(BaseModel):
    task: str
    done: bool = False
# 模拟数据库
todos_db = {}
todo_id_counter = 1
@app.get("/")
def read_root():
    return {"message": "Welcome to the TodoMVC API"}
@app.get("/todos", response_model=list[Todo])
def get_all_todos():
    """列出所有待办事项"""
    return list(todos_db.values())
@app.post("/todos", response_model=Todo, status_code=201)
def create_todo(todo: Todo):
    """创建一个新的待办事项"""
    global todo_id_counter
    todo_id = todo_id_counter
    todos_db[todo_id] = todo
    todo_id_counter += 1
    return todo
@app.get("/todos/{todo_id}", response_model=Todo)
def get_todo(todo_id: int):
    """获取单个待办事项"""
    todo = todos_db.get(todo_id)
    if not todo:
        raise HTTPException(status_code=404, detail="Todo not found")
    return todo
@app.put("/todos/{todo_id}", response_model=Todo)
def update_todo(todo_id: int, todo: Todo):
    """更新一个待办事项"""
    if todo_id not in todos_db:
        raise HTTPException(status_code=404, detail="Todo not found")
    todos_db[todo_id] = todo
    return todo
@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):
    """删除一个待办事项"""
    if todo_id not in todos_db:
        raise HTTPException(status_code=404, detail="Todo not found")
    del todos_db[todo_id]
    return {"detail": "Todo deleted successfully"}
# 运行命令: uvicorn main:app --reload

运行并访问文档

uvicorn main:app --reload

然后打开浏览器访问 http://127.0.0.1:8000/docs,FastAPI 会自动生成一个 Swagger UI 界面,访问 http://127.0.0.1:8000/redoc 可以看到 ReDoc 风格的文档。


API 文档自动化

好的 API 必须有好的文档,现代 Python 框架极大地简化了这一过程。

  • Swagger / OpenAPI: 一套用于描述 API 的规范,描述文件通常为 openapi.jsonopenapi.yaml
  • Swagger UI: 一个基于 OpenAPI 规范的 Web 应用,可以将 API 文档渲染成交互式的界面,允许开发者直接在浏览器中测试 API。
  • ReDoc: 另一个流行的 OpenAPI 文档渲染器,界面更简洁,专注于阅读。

FastAPI 和 Flask-RESTx 的最大优势之一就是它们能根据你的代码和模型定义,自动生成 OpenAPI 规范,并附带 Swagger UI 和 ReDoc。 这意味着你的代码和文档始终保持同步。


进阶主题

数据库集成

在真实应用中,你需要连接数据库。

  • SQLAlchemy: Python 最流行的 ORM,支持多种数据库(PostgreSQL, MySQL, SQLite 等)。
  • Django ORM: 如果使用 Django,这是内置的 ORM。
  • MongoDB: 使用 pymongo 库进行连接。

示例 (使用 SQLAlchemy with Flask):

from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db'
db = SQLAlchemy(app)
class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    task = db.Column(db.String(200), nullable=False)
    done = db.Column(db.Boolean, default=False)
# 在你的视图中,不再使用模拟数据库,而是使用 db.session
#  new_todo = Todo(task=args['task'])
# db.session.add(new_todo)
# db.session.commit()

测试

API 必须经过测试。

  • pytest: Python 最流行的测试框架。
  • requests: 用于向你的 API 发送 HTTP 请求进行测试。
  • httpx: 一个现代的、异步的 HTTP 客户端,是 requests 的一个很好的替代品。

示例 (使用 pytestrequests 测试 FastAPI):

# test_main.py
import pytest
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_create_todo():
    response = client.post("/todos", json={"task": "Test a new todo"})
    assert response.status_code == 201
    assert response.json()["task"] == "Test a new todo"
def test_get_todos():
    # 先创建一个
    client.post("/todos", json={"task": "Get all todos test"})
    # 再获取所有
    response = client.get("/todos")
    assert response.status_code == 200
    assert len(response.json()) > 0

部署

开发完成后,你需要将 API 部署到服务器上。

  • ASGI 服务器: 用于运行异步应用(如 FastAPI)或兼容 ASGI 的 WSGI 应用。
    • Uvicorn: 轻量级,适合开发和生产。
    • Gunicorn: 更传统的 WSGI 服务器,也可以配合 Uvicorn 运行 ASGI 应用。
  • 容器化: 使用 Docker 将你的应用及其依赖打包成一个容器,实现环境一致性和易于部署。
  • 云平台: 将容器部署到云服务上,如 AWS, Google Cloud, Azure,它们提供了负载均衡、自动扩展等强大功能。

特性 Flask + Flask-RESTx Django REST framework FastAPI
易用性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
性能 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
文档生成 ⭐⭐⭐⭐⭐ (自动 Swagger) ⭐⭐⭐⭐⭐ (自动 OpenAPI) ⭐⭐⭐⭐⭐ (自动 Swagger/ReDoc)
功能丰富度 ⭐⭐⭐ (需扩展) ⭐⭐⭐⭐⭐ (内置丰富功能) ⭐⭐⭐⭐ (核心功能强大,依赖第三方)
学习曲线 平缓 较陡 平缓

如何选择?

  • 初学者 / 小型项目 / 微服务: FlaskFastAPI 都是绝佳选择,FastAPI 的性能和现代特性尤其吸引人。
  • 大型项目 / 基于 Django 的项目: Django REST framework 是不二之选,它提供了企业级所需的一切。
  • 追求极致性能 / 现代化 API: FastAPI 是首选,其异步支持和自动数据验证/文档生成非常强大。

希望这份全面的指南能帮助你开始在 Python 世界中构建 RESTful API!

分享:
扫描分享到社交APP
上一篇
下一篇