本文目录导读:

- 使用 FastAPI + Swagger UI(推荐)
- 使用 Flask-RESTx
- 使用 Django REST Framework + Swagger
- 使用 APIDOC 生成静态文档
- 使用 Connexion + OpenAPI
- 生成 Markdown 格式的静态文档
- 安装依赖
- 运行方式
- 推荐方案
Python实现接口文档生成有多种方式,我为你介绍几种常用的方法:
使用 FastAPI + Swagger UI(推荐)
FastAPI 自动生成 OpenAPI 规范的接口文档:
from fastapi import FastAPI, Query, Path, Body
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
# 创建 FastAPI 实例
app = FastAPI("用户管理系统 API",
description="这是一个用户管理系统的接口文档",
version="1.0.0",
docs_url="/docs", # Swagger UI 路径
redoc_url="/redoc" # ReDoc 路径
)
# 定义数据模型
class User(BaseModel):
username: str
email: str
full_name: Optional[str] = None
age: Optional[int] = None
created_at: datetime = datetime.now()
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=50, description="用户名")
email: str = Field(..., description="邮箱地址")
full_name: Optional[str] = Field(None, description="用户全名")
password: str = Field(..., min_length=6, description="密码")
# 示例数据
users_db = {}
@app.get("/")
async def root():
"""
根路径,返回欢迎信息
"""
return {"message": "欢迎使用用户管理系统 API"}
@app.get("/users",
tags=["用户管理"],
summary="获取所有用户",
description="返回系统中所有用户的列表")
async def get_users(
skip: int = Query(0, description="跳过的记录数"),
limit: int = Query(10, description="返回的记录数")
):
"""
获取用户列表
- **skip**: 跳过的记录数,默认为0
- **limit**: 返回的记录数,默认为10
"""
users = list(users_db.values())[skip:skip + limit]
return {"total": len(users_db), "users": users}
@app.post("/users",
tags=["用户管理"],
summary="创建用户",
response_model=User,
status_code=201)
async def create_user(user: UserCreate):
"""
创建一个新用户
- **username**: 用户名(必填,3-50个字符)
- **email**: 邮箱地址(必填)
- **full_name**: 用户全名(可选)
- **password**: 密码(必填,至少6个字符)
"""
if user.username in users_db:
return {"error": "用户已存在"}
new_user = User(
username=user.username,
email=user.email,
full_name=user.full_name
)
users_db[user.username] = new_user
return new_user
@app.get("/users/{user_id}",
tags=["用户管理"],
summary="获取指定用户")
async def get_user(
user_id: str = Path(..., description="用户ID"),
detail: bool = Query(False, description="是否返回详细信息")
):
"""
根据用户ID获取用户信息
"""
if user_id not in users_db:
return {"error": "用户不存在"}
user = users_db[user_id]
if detail:
return {"user": user, "detail": True}
return {"user": user}
@app.put("/users/{user_id}",
tags=["用户管理"],
summary="更新用户信息")
async def update_user(
user_id: str = Path(..., description="用户ID"),
user: UserCreate = Body(..., description="更新的用户信息")
):
"""
更新指定用户的信息
"""
if user_id not in users_db:
return {"error": "用户不存在"}
updated_user = User(
username=user.username,
email=user.email,
full_name=user.full_name
)
users_db[user_id] = updated_user
return {"message": "用户更新成功", "user": updated_user}
@app.delete("/users/{user_id}",
tags=["用户管理"],
summary="删除用户")
async def delete_user(
user_id: str = Path(..., description="用户ID")
):
"""
删除指定用户
"""
if user_id not in users_db:
return {"error": "用户不存在"}
del users_db[user_id]
return {"message": "用户删除成功"}
# 运行服务
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
使用 Flask-RESTx
Flask的扩展,可以生成Swagger文档:
from flask import Flask
from flask_restx import Api, Resource, fields, reqparse
from datetime import datetime
app = Flask(__name__)
# 创建 API 实例
api = Api(
app,
version='1.0','商品管理系统 API',
description='商品管理系统的接口文档',
doc='/docs/' # Swagger UI 路径
)
# 定义命名空间
ns = api.namespace('products', description='商品操作')
# 定义数据模型
product_model = api.model('Product', {
'id': fields.Integer(readonly=True, description='商品ID'),
'name': fields.String(required=True, description='商品名称'),
'price': fields.Float(required=True, description='商品价格'),
'category': fields.String(description='商品分类'),
'created_at': fields.DateTime(description='创建时间')
})
product_input = api.model('ProductInput', {
'name': fields.String(required=True, description='商品名称'),
'price': fields.Float(required=True, description='商品价格'),
'category': fields.String(description='商品分类')
})
# 模拟数据库
products = {}
next_id = 1
@ns.route('/')
class ProductList(Resource):
@ns.doc('list_products')
@ns.marshal_list_with(product_model)
def get(self):
"""获取所有商品"""
return list(products.values())
@ns.doc('create_product')
@ns.expect(product_input)
@ns.marshal_with(product_model, code=201)
def post(self):
"""创建新商品"""
global next_id
data = api.payload
product = {
'id': next_id,
'name': data['name'],
'price': data['price'],
'category': data.get('category', ''),
'created_at': datetime.now()
}
products[next_id] = product
next_id += 1
return product, 201
@ns.route('/<int:id>')
@ns.response(404, '商品不存在')
@ns.param('id', '商品ID')
class Product(Resource):
@ns.doc('get_product')
@ns.marshal_with(product_model)
def get(self, id):
"""获取指定商品"""
if id not in products:
api.abort(404)
return products[id]
@ns.doc('update_product')
@ns.expect(product_input)
@ns.marshal_with(product_model)
def put(self, id):
"""更新商品信息"""
if id not in products:
api.abort(404)
data = api.payload
products[id].update({
'name': data['name'],
'price': data['price'],
'category': data.get('category', '')
})
return products[id]
@ns.doc('delete_product')
@ns.response(204, '商品已删除')
def delete(self, id):
"""删除商品"""
if id not in products:
api.abort(404)
del products[id]
return '', 204
if __name__ == '__main__':
app.run(debug=True, port=5000)
使用 Django REST Framework + Swagger
# settings.py
INSTALLED_APPS = [
'rest_framework',
'drf_yasg', # Django REST Swagger
# ...
]
# urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="博客系统 API",
default_version='v1',
description="博客系统的API接口文档",
terms_of_service="https://www.example.com/terms/",
contact=openapi.Contact(email="contact@example.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=[permissions.AllowAny],
)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('blog.urls')),
# Swagger UI
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
# ReDoc
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
# blog/views.py
from rest_framework import viewsets
from rest_framework.decorators import action
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
@swagger_auto_schema(
operation_description="获取所有文章列表",
operation_summary="文章列表",
manual_parameters=[
openapi.Parameter(
'category',
openapi.IN_QUERY,
description="按分类筛选",
type=openapi.TYPE_STRING
),
openapi.Parameter(
'search',
openapi.IN_QUERY,
description="搜索关键词",
type=openapi.TYPE_STRING
),
],
responses={
200: PostSerializer(many=True),
400: "请求参数错误"
}
)
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
@swagger_auto_schema(
operation_description="创建新文章",
operation_summary="创建文章",
request_body=PostSerializer,
responses={
201: PostSerializer(),
400: "数据验证失败"
}
)
def create(self, request, *args, **kwargs):
return super().create(request, *args, **kwargs)
使用 APIDOC 生成静态文档
// apidoc.json
{
"name": "示例API",
"version": "1.0.0",
"description": "这是一个示例API文档",: "API文档",
"url": "http://api.example.com"
}
// app.py - 添加注释
"""
@api {get} /api/users 获取用户列表
@apiName GetUsers
@apiGroup User
@apiVersion 1.0.0
@apiParam {Number} [page=1] 页码
@apiParam {Number} [limit=10] 每页数量
@apiSuccess {Number} code 状态码
@apiSuccess {String} message 提示信息
@apiSuccess {Object[]} data 用户列表
@apiSuccess {Number} data.id 用户ID
@apiSuccess {String} data.name 用户名
@apiSuccess {String} data.email 邮箱
@apiSuccessExample {json} 成功响应:
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"name": "张三",
"email": "zhangsan@example.com"
}
]
}
@apiError {Number} code 错误码
@apiError {String} message 错误信息
@apiErrorExample {json} 错误响应:
{
"code": 404,
"message": "用户不存在"
}
"""
使用 Connexion + OpenAPI
# openapi.yaml
openapi: "3.0.0"
info: 任务管理系统
version: "1.0.0"
description: 任务管理系统的API文档
paths:
/tasks:
get:
summary: 获取所有任务
operationId: app.get_tasks
parameters:
- name: status
in: query
schema:
type: string
description: 任务状态
responses:
'200':
description: 成功获取任务列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Task'
post:
summary: 创建新任务
operationId: app.create_task
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TaskInput'
responses:
'201':
description: 任务创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
/tasks/{task_id}:
get:
summary: 获取指定任务
operationId: app.get_task
parameters:
- name: task_id
in: path
required: true
schema:
type: integer
responses:
'200':
description: 成功获取任务
components:
schemas:
Task:
type: object
properties:
id:
type: integer
title:
type: string
description:
type: string
status:
type: string
enum: [todo, in_progress, done]
created_at:
type: string
format: date-time
TaskInput:
type: object
required:
- title
properties:
title:
type: string
description: 任务标题
description:
type: string
description: 任务描述
status:
type: string
default: todo
# app.py
import connexion
from datetime import datetime
app = connexion.FlaskApp(__name__)
app.add_api('openapi.yaml')
tasks = {}
next_id = 1
def get_tasks(status=None):
"""获取所有任务"""
if status:
filtered = [t for t in tasks.values() if t['status'] == status]
return filtered
return list(tasks.values())
def create_task(body):
"""创建新任务"""
global next_id
task = {
'id': next_id,
'title': body['title'],
'description': body.get('description', ''),
'status': body.get('status', 'todo'),
'created_at': datetime.now().isoformat()
}
tasks[next_id] = task
next_id += 1
return task, 201
def get_task(task_id):
"""获取指定任务"""
return tasks.get(task_id, {'error': '任务不存在'})
if __name__ == '__main__':
app.run(port=8080)
生成 Markdown 格式的静态文档
# docs_generator.py
from typing import Dict, List
import json
class APIDocGenerator:
def __init__(self, title: str, version: str, description: str):
self.title = title
self.version = version
self.description = description
self.endpoints = []
def add_endpoint(self, method: str, path: str, summary: str, description: str,
parameters: List[Dict] = None, request_body: Dict = None,
responses: Dict = None):
"""添加API端点"""
endpoint = {
'method': method,
'path': path,
'summary': summary,
'description': description,
'parameters': parameters or [],
'request_body': request_body,
'responses': responses or {}
}
self.endpoints.append(endpoint)
def generate_markdown(self) -> str:
"""生成Markdown格式文档"""
md = f"""# {self.title}
> API版本: {self.version}
{self.description}
## 接口列表
"""
for endpoint in self.endpoints:
md += f"""### {endpoint['method']} {endpoint['path']}
**{endpoint['summary']}**
{endpoint['description']}
"""
if endpoint['parameters']:
md += "#### 请求参数\n\n"
md += "| 参数名 | 类型 | 必填 | 描述 |\n"
md += "|--------|------|------|------|\n"
for param in endpoint['parameters']:
required = "是" if param.get('required') else "否"
md += f"| {param['name']} | {param['type']} | {required} | {param['description']} |\n"
md += "\n"
if endpoint['request_body']:
md += "#### 请求体\n\n```json\n"
md += json.dumps(endpoint['request_body'], indent=2)
md += "\n```\n\n"
if endpoint['responses']:
md += "#### 响应示例\n\n"
for status, example in endpoint['responses'].items():
md += f"**{status}**\n\n```json\n"
md += json.dumps(example, indent=2)
md += "\n```\n\n"
return md
# 使用示例
if __name__ == "__main__":
doc = APIDocGenerator(
title="文件管理系统 API",
version="1.0.0",
description="文件上传、下载、管理等接口"
)
doc.add_endpoint(
method="GET",
path="/api/files",
summary="获取文件列表",
description="获取用户所有文件的列表",
parameters=[
{"name": "page", "type": "integer", "required": False, "description": "页码"},
{"name": "limit", "type": "integer", "required": False, "description": "每页数量"}
],
responses={
200: {"files": [{"id": 1, "name": "file.txt", "size": 1024}], "total": 100}
}
)
doc.add_endpoint(
method="POST",
path="/api/upload",
summary="上传文件",
description="上传文件到服务器",
request_body={"file": "文件二进制数据", "type": "file"},
responses={
201: {"id": 1, "url": "http://example.com/file.txt"}
}
)
markdown = doc.generate_markdown()
with open("api_documentation.md", "w", encoding="utf-8") as f:
f.write(markdown)
print("文档已生成: api_documentation.md")
安装依赖
根据不同方案安装对应的依赖:
# FastAPI pip install fastapi uvicorn # Flask-RESTx pip install flask flask-restx # Django REST Framework + Swagger pip install djangorestframework drf-yasg # APIDOC (需要Node.js) npm install -g apidoc # Connexion pip install connexion[swagger-ui]
运行方式
# FastAPI python fastapi_app.py # 访问 http://localhost:8000/docs (Swagger UI) # 访问 http://localhost:8000/redoc (ReDoc) # Flask-RESTx python flask_app.py # 访问 http://localhost:5000/docs/ # Django python manage.py runserver # 访问 http://localhost:8000/swagger/ (Swagger UI) # 访问 http://localhost:8000/redoc/ (ReDoc) # APIDOC apidoc -i app.py -o docs/ # 在浏览器打开 docs/index.html # Connexion python connexion_app.py # 访问 http://localhost:8080/ui/
推荐方案
- 新项目: 推荐使用 FastAPI + Swagger UI,自动生成文档,简洁高效
- 已有Flask项目: 使用 Flask-RESTx 或 Connexion
- Django项目: 使用 Django REST Framework + drf-yasg
- 纯文档生成: 使用 APIDOC 或自定义Markdown生成器
这些方案都能生成美观、交互式的API文档,方便前后端协作开发和API测试。