diff --git a/README.md b/README.md index 90405a0..13009af 100644 --- a/README.md +++ b/README.md @@ -1457,6 +1457,174 @@ celery -A diary_family flower --port=5555 访问 http://your-server:5555 查看任务监控界面。 +## API接口文档 + +系统提供RESTful API接口,用于外部客户端提交汇总记录。 + +### 1. 汇总记录提交API + +用于外部客户端(如监控脚本、自动化任务)向系统提交汇总记录。 + +#### 请求信息 + +- **URL**: `/api/v1/summary/submit/` +- **方法**: `POST` +- **Content-Type**: `application/x-www-form-urlencoded` 或 `multipart/form-data` + +#### 请求参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-------|------|------|------| +| content | string | 是 | 汇总记录内容,最大长度不限 | + +#### 响应格式 + +**成功响应** (HTTP 200): +```json +{ + "success": true, + "message": "提交成功", + "id": 123 +} +``` + +**失败响应** (HTTP 400/500): +```json +{ + "success": false, + "message": "错误信息描述" +} +``` + +#### 调用示例 + +```bash +# 使用 curl 提交汇总记录 +curl -X POST http://your-server/api/v1/summary/submit/ \ + -d "content=这是自动提交的汇总内容" + +# Python requests 调用示例 +import requests + +url = "http://your-server/api/v1/summary/submit/" +data = { + "content": "监控报告:系统运行正常,CPU使用率15%,内存使用率42%" +} + +response = requests.post(url, data=data) +result = response.json() +print(result) +``` + +#### 客户端自动提交示例 + +创建一个Python脚本用于自动提交系统监控数据: + +```python +#!/usr/bin/env python3 +# submit_summary.py + +import socket +import psutil +import requests +from datetime import datetime + +def get_system_info(): + """获取系统基本信息""" + cpu_percent = psutil.cpu_percent(interval=1) + memory = psutil.virtual_memory() + disk = psutil.disk_usage('/') + return { + 'cpu': cpu_percent, + 'memory': memory.percent, + 'disk': disk.percent + } + +def submit_summary(content): + """提交汇总记录到家庭日报系统""" + url = "http://your-server/api/v1/summary/submit/" + try: + response = requests.post(url, data={'content': content}, timeout=10) + result = response.json() + if result['success']: + print(f"提交成功,记录ID: {result['id']}") + else: + print(f"提交失败: {result['message']}") + except Exception as e: + print(f"请求异常: {str(e)}") + +if __name__ == "__main__": + info = get_system_info() + timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + content = f"[系统监控 {timestamp}] CPU使用率: {info['cpu']}%, 内存使用率: {info['memory']}%, 磁盘使用率: {info['disk']}%" + submit_summary(content) +``` + +#### 注意事项 + +1. **数据验证**:API仅接受以下条件的记录: + - 分类必须为"定期" + - 发言人必须为"机器人" + - 内容不能为空 + +2. **来源自动生成**:系统会自动获取客户端的主机名和IP地址,填充到source字段。 + +3. **日期自动设置**:记录日期自动设置为提交时的日期。 + +4. **错误处理**:如果分类或发言人不存在,API会返回错误信息。 + +### 2. 初始化必需数据 + +在使用API提交功能前,需要确保数据库中存在以下数据: + +#### 方法一:Django Shell初始化 + +```bash +python manage.py shell -c " +from core.models import SummaryCategory, FamilyMember + +# 创建'定期'分类(如果不存在) +category, created = SummaryCategory.objects.get_or_create(name='定期') +if created: + print('创建分类: 定期') +else: + print('分类已存在: 定期') + +# 创建'机器人'发言人(如果不存在) +speaker, created = FamilyMember.objects.get_or_create(name='机器人') +if created: + print('创建发言人: 机器人') +else: + print('发言人已存在: 机器人') + +print('初始化完成') +" +``` + +#### 方法二:Django Admin后台创建 + +1. 登录后台管理:`/houtai` +2. 在 **汇总分类** 中添加名为"定期"的分类 +3. 在 **家庭成员** 中添加名为"机器人"的成员 + +### 3. 常见问题排查 + +#### 问题1:提交返回"分类 '定期' 不存在" + +**解决方法**:在数据库中创建该分类(见上方初始化方法) + +#### 问题2:提交返回"发言人 '机器人' 不存在" + +**解决方法**:在数据库中创建该发言人(见上方初始化方法) + +#### 问题3:提交返回"内容不能为空" + +**解决方法**:确保请求中包含 `content` 参数且不为空 + +#### 问题4:返回HTTP 405错误 + +**解决方法**:确认使用的是POST方法,不是GET方法 + ## 注意事项 1. 定期备份数据库 diff --git a/core/urls.py b/core/urls.py index 745fe09..0a97875 100644 --- a/core/urls.py +++ b/core/urls.py @@ -29,6 +29,9 @@ urlpatterns = [ path('summaries//edit/', views.edit_summary, name='edit_summary'), path('summaries//delete/', views.delete_summary, name='delete_summary'), + # API - 汇总记录提交 + path('api/v1/summary/submit/', views.api_submit_summary, name='api_submit_summary'), + # 家庭事项 path('family-tasks/', views.family_tasks, name='family_tasks'), path('family-tasks/add/', views.add_family_task, name='add_family_task'), diff --git a/core/views.py b/core/views.py index 2c9da08..831bd8e 100644 --- a/core/views.py +++ b/core/views.py @@ -804,3 +804,57 @@ def pdf_list(request): } return render(request, 'core/pdf_list.html', context) + +def api_submit_summary(request): + """API提交汇总记录 - 仅接受指定分类和发言人的记录""" + logger.info("API: 收到汇总记录提交请求") + + if request.method != 'POST': + return JsonResponse({'success': False, 'message': '只支持POST请求'}, status=405) + + try: + import socket + import uuid + + content = request.POST.get('content', '').strip() + + if not content: + return JsonResponse({'success': False, 'message': '内容不能为空'}, status=400) + + category_name = "定期" + speaker_name = "机器人" + + try: + category = SummaryCategory.objects.get(name=category_name) + except SummaryCategory.DoesNotExist: + logger.error(f"API: 分类 '{category_name}' 不存在") + return JsonResponse({'success': False, 'message': f"分类 '{category_name}' 不存在"}, status=400) + + try: + speaker = FamilyMember.objects.get(name=speaker_name) + except FamilyMember.DoesNotExist: + logger.error(f"API: 发言人 '{speaker_name}' 不存在") + return JsonResponse({'success': False, 'message': f"发言人 '{speaker_name}' 不存在"}, status=400) + + hostname = socket.gethostname() + local_ip = socket.gethostbyname(hostname) + source = f"{hostname} ({local_ip})" + + summary = Summary.objects.create( + date=timezone.now().date(), + category=category, + speaker=speaker, + content=content, + source=source + ) + + logger.info(f"API: 汇总记录创建成功,ID={summary.id}") + return JsonResponse({ + 'success': True, + 'message': '提交成功', + 'id': summary.id + }) + + except Exception as e: + logger.error(f"API: 提交汇总记录失败: {str(e)}") + return JsonResponse({'success': False, 'message': f"提交失败: {str(e)}"}, status=500)