feat(api): 添加汇总记录提交API接口

添加新的API端点/api/v1/summary/submit/用于外部客户端提交汇总记录
自动设置分类为"定期",发言人为"机器人"
包含请求参数验证和错误处理
更新README文档添加API使用说明和示例代码
This commit is contained in:
2026-01-25 21:36:48 +08:00
parent d5fb589bb5
commit 143e228d8d
3 changed files with 225 additions and 0 deletions

168
README.md
View File

@@ -1457,6 +1457,174 @@ celery -A diary_family flower --port=5555
访问 http://your-server: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. 定期备份数据库 1. 定期备份数据库

View File

@@ -29,6 +29,9 @@ urlpatterns = [
path('summaries/<int:pk>/edit/', views.edit_summary, name='edit_summary'), path('summaries/<int:pk>/edit/', views.edit_summary, name='edit_summary'),
path('summaries/<int:pk>/delete/', views.delete_summary, name='delete_summary'), path('summaries/<int:pk>/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/', views.family_tasks, name='family_tasks'),
path('family-tasks/add/', views.add_family_task, name='add_family_task'), path('family-tasks/add/', views.add_family_task, name='add_family_task'),

View File

@@ -804,3 +804,57 @@ def pdf_list(request):
} }
return render(request, 'core/pdf_list.html', context) 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)