API文档自动化生成系统

一个基于Django REST Framework ViewSet自动分析并生成OpenAPI 3.0规范API文档的全自动化系统,支持Swagger UI展示。

  • by namyoungpark-2
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 namyoungpark-2/docs-mcp-server

使用说明

MCP API文档自动化系统

通过自动分析Django REST Framework ViewSet,生成OpenAPI 3.0规范的API文档的完全自动化系统。

📋 目录

🎯 项目概述

目的

  • 自动检测和分析Django项目的ViewSet
  • 根据实际serializer字段生成准确的OpenAPI 3.0规范
  • 完全自动化请求/响应参数、标题和主体信息
  • 通过Swagger UI提供直观的API文档

关键特性

  • ✅ 完全自动化:自动检测ViewSet,无需手动设置
  • ✅ 正确的模式:实际serializer字段1:1反映
  • ✅ 125个端点:支持所有ViewSet CRUD操作
  • ✅ 实时生成:更改代码时立即更新文档
  • ✅ JavaScript兼容:完全支持Swagger UI

🏗️ 系统体系结构

┌─────────────────┐    HTTP Request    ┌─────────────────┐
│   MCP Server    │ ──────────────────► │ Python Parser   │
│  (Spring Boot)  │                    │   (FastAPI)     │
│   Port: 8080    │                    │   Port: 8009    │
└─────────────────┘                    └─────────────────┘
         │                                       │
         │                                       │
         ▼                                       ▼
┌─────────────────┐                    ┌─────────────────┐
│   Swagger UI    │                    │ Django Project  │
│  API Docs HTML  │                    │  ViewSet Files  │
│  /api-docs/html │                    │  /shared_repos/ │
└─────────────────┘                    └─────────────────┘

元件说明

  1. Python解析器(FastAPI)

    • Django ViewSet自动检测和分析
    • 创建OpenAPI 3.0规范
    • 提取实际serializer字段
  2. MCP服务器(春季启动)

    • 提供Swagger UI
    • 提供JSON API文档服务
    • 代理角色
  3. Django项目

    • 分析的ViewSet文件
    • 实际serializer定义

🚀 主要功能

1.自动检测ViewSet

  • app/ 扫描目录中的所有应用程序
  • views.py 或者 views/ 分析文件夹中的文件
  • class \w+ViewSet 自动发现模式

2.提取Serializer字段

  • serializer_class 自动检测属性
  • 提取实际字段类型、nullable和required信息
  • 嵌套serializer支持

3.创建OpenAPI 3.0规范

  • 请求参数(查询、标题、主体)
  • 响应模式(按状态代码)
  • 认证信息(Authorization标头)
  • 分页、搜索、过滤지원

4.自动创建CRUD端点

  • 获取 /api/v1/{resource}/ -查看列表
  • 发布 /api/v1/{resource}/ -创建
  • 获取 /api/v1/{resource}/{id}/ -详细查询
  • 放 /api/v1/{resource}/{id}/ -修改
  • 删除 /api/v1/{resource}/{id}/ -删除

🛠️ 技术堆栈

后端

  • Python 3.12.2:主解析逻辑
  • 快速 API:Python解析器서버
  • 姜戈:分析项目
  • Django REST框架:ViewSet分析

前端

  • Spring Boot:MCP服务器
  • Swagger用户界面:API文档接口
  • 百里香叶:HTML模板

开发工具

  • Gradle:Spring Boot版本
  • 优维康:FastAPI服务器
  • watch文件:自动重新加载

📁 项目结构

mcp-docs-server-final/
├── python-parser/                    # Python Parser 서버
│   ├── main.py                      # FastAPI 서버 진입점
│   ├── src/
│   │   ├── application/             # 애플리케이션 레이어
│   │   │   └── use_cases/
│   │   │       └── generate_api_docs_use_case.py
│   │   ├── domain/                  # 도메인 레이어
│   │   │   └── entities/
│   │   │       ├── api_documentation.py
│   │   │       ├── api_endpoint.py
│   │   │       └── api_parameter.py
│   │   ├── infrastructure/          # 인프라 레이어
│   │   │   ├── generators/
│   │   │   │   └── api_documentation_generator.py
│   │   │   └── parsers/
│   │   │       └── python_parser.py
│   │   └── presentation/            # 프레젠테이션 레이어
│   │       └── controllers/
│   │           └── api_docs_controller.py
│   ├── generated_docs/              # 생성된 API 문서
│   │   └── ucms-be_api_docs.json
│   └── requirements.txt
├── shared_repos/                    # 분석 대상 Django 프로젝트
│   └── ucms-be/
│       └── app/
│           ├── account/
│           ├── revenue/
│           ├── content/
│           └── ... (기타 앱들)
├── src/                             # Spring Boot MCP 서버
│   └── main/
│       ├── java/
│       │   └── com/odk/
│       │       └── controller/
│       │           └── ApiDocsController.java
│       └── resources/
│           ├── templates/
│           │   └── swagger-viewer.html
│           └── static/
│               └── openapi/
├── build.gradle                     # Spring Boot 빌드 설정
└── docker-compose.override.yml      # Docker 설정

🔧 本地首选参数

1.设置Python环境

# Python 3.12.2 설치 (pyenv 사용)
pyenv install 3.12.2
pyenv local 3.12.2

# 가상환경 생성 및 활성화
cd python-parser
python -m venv venv
source venv/bin/activate  # macOS/Linux
# 또는
venv\Scripts\activate     # Windows

2.安装Python依赖性

cd python-parser
pip install -r requirements.txt

3.Spring Boot首选参数

# Java 17 이상 필요
java -version

# Gradle 빌드
./gradlew build

🚀 执行方法

1.启动Python Parser服务器

cd python-parser
python main.py

服务器信息:

  • 网址: http://localhost:8009
  • 自动重新加载:启用
  • Django环境:自动设置

2.启动Spring Boot MCP服务器

# 프로젝트 루트에서
./gradlew bootRun

服务器信息:

  • 网址: http://localhost:8080
  • Swagger用户界面: http://localhost:8080/api-docs/html
  • JSON API: http://localhost:8080/api-docs/json

3.生成API文档

# Python Parser 서버가 실행 중인 상태에서
curl -X POST "http://localhost:8009/api/v1/docs/generate/ucms-be?base_url=http://localhost:8009&save_to_file=true"

📖 API使用

1.API文档生成端点

POST /api/v1/docs/generate/{project_name}

参数:

  • project_name:项目名称(例如ucms-be)
  • base_url:默认URL(例如:http://localhost:8009)
  • save_to_file:是否保存文件(true/false)

回复:

{
  "success": true,
  "message": "API documentation generated successfully",
  "data": {
    "endpoints_count": 125,
    "file_path": "generated_docs/ucms-be_api_docs.json"
  }
}

2.确认生成的文档

  • Swagger用户界面: http://localhost:8080/api-docs/html
  • JSON文件: http://localhost:8080/api-docs/json
  • 本地文件: python-parser/generated_docs/ucms-be_api_docs.json

🔍 实施详细信息

1.ViewSet自动检测逻辑

def discover_viewsets(django_app_path: str) -> List[Tuple[str, str]]:
    """
    Django 앱 디렉토리에서 ViewSet 클래스 자동 탐지

    Args:
        django_app_path: Django 앱 경로

    Returns:
        List[Tuple[앱명.ViewSet명, URL경로]]
    """
    viewsets = []

    # app/ 디렉토리 내 모든 앱 스캔
    for app_dir in os.listdir(django_app_path):
        app_path = os.path.join(django_app_path, app_dir)

        if os.path.isdir(app_path):
            # views.py 파일 확인
            views_file = os.path.join(app_path, "views.py")
            if os.path.exists(views_file):
                viewsets.extend(extract_viewsets_from_file(views_file, app_dir))

            # views/ 폴더 확인
            views_dir = os.path.join(app_path, "views")
            if os.path.isdir(views_dir):
                for file in os.listdir(views_dir):
                    if file.endswith(".py"):
                        file_path = os.path.join(views_dir, file)
                        viewsets.extend(extract_viewsets_from_file(file_path, f"{app_dir}/views/{file[:-3]}"))

    return viewsets

2.Serializer字段提取逻辑

def extract_serializer_from_viewset(viewset_class, viewset_name: str) -> Dict[str, Any]:
    """
    ViewSet에서 실제 사용하는 serializer 필드 추출

    Args:
        viewset_class: ViewSet 클래스
        viewset_name: ViewSet 이름

    Returns:
        Dict[str, Any]: 필드 정보 딕셔너리
    """
    try:
        # 1. serializer_class 속성 확인
        if hasattr(viewset_class, 'serializer_class'):
            serializer_class = viewset_class.serializer_class
            return extract_serializer_fields(serializer_class)

        # 2. get_serializer_class 메서드 확인
        if hasattr(viewset_class, 'get_serializer_class'):
            serializer_class = viewset_class.get_serializer_class()
            return extract_serializer_fields(serializer_class)

        # 3. 소스 코드 분석으로 serializer 패턴 찾기
        return extract_serializer_from_source(viewset_class, viewset_name)

    except Exception as e:
        print(f"[문서 자동화] {viewset_name}에서 serializer 필드 추출 실패: {e}")
        return None

3.OpenAPI规范生成逻辑

def generate_openapi_for_viewset(
    viewset_name: str,
    file_path: str,
    base_url: str,
    model_name: str = None,
) -> List[ApiEndpoint]:
    """
    ViewSet에서 OpenAPI 엔드포인트 생성

    Args:
        viewset_name: ViewSet 클래스명
        file_path: ViewSet 파일 경로
        base_url: 기본 URL
        model_name: 모델명 (선택사항)

    Returns:
        List[ApiEndpoint]: 생성된 엔드포인트 목록
    """
    # 1. ViewSet 클래스 import
    viewset_class = import_viewset_class(file_path, viewset_name)

    # 2. Serializer 필드 추출
    serializer_fields = extract_serializer_from_viewset(viewset_class, viewset_name)

    # 3. URL 경로 생성
    resource_name = model_name or viewset_name.replace('ViewSet', '').lower()
    base_path = f"/api/v1/{resource_name}/"

    # 4. CRUD 엔드포인트 생성
    endpoints = []

    # GET /api/v1/{resource}/ - 목록 조회
    endpoints.append(ApiEndpoint(
        path=base_path,
        method=HttpMethod.GET,
        summary=f"Get {resource_name} list",
        description=f"Retrieve a list of {resource_name}",
        parameters=generate_list_parameters(),
        responses=generate_list_responses(serializer_fields)
    ))

    # POST /api/v1/{resource}/ - 생성
    endpoints.append(ApiEndpoint(
        path=base_path,
        method=HttpMethod.POST,
        summary=f"Create {resource_name}",
        description=f"Create a new {resource_name}",
        parameters=generate_create_parameters(),
        request_body=generate_request_body(serializer_fields),
        responses=generate_create_responses(serializer_fields)
    ))

    # 기타 CRUD 엔드포인트들...

    return endpoints

🧪 测试方法

1.测试单位

cd python-parser
python -m pytest tests/

2.集成测试

# 1. Python Parser 서버 시작
cd python-parser
python main.py

# 2. API 문서 생성 요청
curl -X POST "http://localhost:8009/api/v1/docs/generate/ucms-be?base_url=http://localhost:8009&save_to_file=true"

# 3. 생성된 파일 확인
ls -la generated_docs/
cat generated_docs/ucms-be_api_docs.json | jq '.paths | keys | length'

3.测试Swagger UI

# 1. Spring Boot 서버 시작
./gradlew bootRun

# 2. 브라우저에서 확인
open http://localhost:8080/api-docs/html

4.按端点进行测试

# Revenue API 테스트
curl -X GET "http://localhost:8080/api-docs/json" | jq '.paths | keys | grep revenue'

# AdminUser API 테스트
curl -X GET "http://localhost:8080/api-docs/json" | jq '.paths | keys | grep adminuser'

📊 生成的API文档示例

1.Revenue API端点

{
  "/api/v1/revenues/": {
    "get": {
      "summary": "Get revenues list",
      "description": "Retrieve a list of revenues",
      "tags": ["revenue"],
      "parameters": [
        {
          "name": "Authorization",
          "in": "header",
          "required": true,
          "description": "Bearer token for authentication",
          "schema": { "type": "string" }
        },
        {
          "name": "page",
          "in": "query",
          "required": false,
          "description": "Page number for pagination",
          "schema": { "type": "integer" }
        }
      ],
      "responses": {
        "200": {
          "description": "Successful response",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": { "type": "integer" },
                  "amount": { "type": "number", "format": "decimal" },
                  "currency": { "type": "string" },
                  "created_at": { "type": "string", "format": "date-time" },
                  "updated_at": { "type": "string", "format": "date-time" }
                }
              }
            }
          }
        }
      }
    }
  }
}

2.生成的端点统计数据

  • 终端合计数量:125个
  • ViewSet计数:25个
  • 主要ViewSet:
    • Revenue(16个字段)
    • RevenueShare(16个字段)
    • AdminUser(8个字段)
    • UserActionHistory(12个字段)
    • VideoSource(23个字段)
    • Series(18个字段)
    • Content(各种字段)
    • 所有其他ViewSet

🔧 故障射击

1.Django环境设置问题

问题: DJANGO_SETTINGS_MODULE 未设置

Error: No module named 'django'

解决方案:

def setup_django_environment(django_app_path: str):
    """Django 환경 설정"""
    import os
    import sys
    import django

    # Django 설정 모듈 환경변수 설정
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

    # 프로젝트 및 앱 경로를 Python 경로에 추가
    project_root = os.path.dirname(django_app_path)
    sys.path.insert(0, project_root)
    sys.path.insert(0, django_app_path)

    # Django 설정
    django.setup()

2.ViewSet Import失败

问题:相对import错误

Error: attempted relative import with no known parent package

解决方案:

def import_viewset_class(file_path: str, viewset_name: str):
    """ViewSet 클래스 import"""
    try:
        # 1. 직접 import 시도
        module_name = get_module_name_from_path(file_path)
        module = importlib.import_module(module_name)
        return getattr(module, viewset_name)
    except ImportError:
        # 2. fallback: 파일 파싱
        return parse_viewset_from_file(file_path, viewset_name)

3.提取Serializer字段失败

问题: cached_property 错误

Error: 'cached_property' object has no attribute 'get_fields'

解决方案:

def extract_serializer_fields(serializer_class):
    """Serializer 필드 추출"""
    try:
        # Serializer 인스턴스 생성
        serializer = serializer_class()

        # fields 속성에 안전하게 접근
        if hasattr(serializer, 'fields'):
            fields = serializer.fields
            return {name: extract_field_schema(field) for name, field in fields.items()}
    except Exception as e:
        print(f"Serializer 필드 추출 실패: {e}")
        return None

4.JavaScript兼容性问题

问题:在Swagger UI中 Object.keys() 错误

TypeError: Cannot convert undefined or null to object

解决方案:

def to_openapi_dict(self) -> Dict[str, Any]:
    """OpenAPI 3.0 형식으로 변환"""
    endpoint_dict = {
        "summary": endpoint.summary,
        "description": endpoint.description,
        "tags": endpoint.tags,
        "deprecated": endpoint.deprecated,
        "parameters": [...],
    }

    # null 값 제거로 JavaScript 호환성 확보
    if endpoint.request_body is not None:
        endpoint_dict["requestBody"] = endpoint.request_body

    if endpoint.responses is not None:
        endpoint_dict["responses"] = endpoint.responses

    return endpoint_dict

📈 性能优化

1.缓存策略

  • ViewSet类import结果缓存
  • 缓存Serializer字段提取结果
  • 通过检测文件更改部分更新

2.并行处理

  • 同时分析多个ViewSet
  • 文件I/O异步处理

3.内存优化

  • 避免创建不必要的对象
  • 优化垃圾收集

🔮 未来改进计划

1.功能扩展

  • []支持创建GraphQL模式
  • []API版本控制
  • []支持自定义筛选/排序
  • []自动生成API测试代码

2.改善性能

  • []引入Redis缓存
  • []优化批处理
  • []监控内存使用情况

3.提高可用性

  • []添加Web界面
  • []实时文档更新
  • []API文档版本控制

📞 支持和联系

有关项目的问题或错误报告请通过热点问题提交。


开发者:人工智能助理
上次更新:2024年12月
版本: 1.0.0