Compare commits
12 Commits
066475c487
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 54130d4401 | |||
| a8e24fad63 | |||
| 97c0e0db0d | |||
| c4086b9f46 | |||
| d7c1d00ba1 | |||
| ddcd490575 | |||
| c71f8f7740 | |||
| de0af70958 | |||
| 2630405dac | |||
| 98925f4cce | |||
| becca344bf | |||
| 527cb1dc3e |
13
.env.example
13
.env.example
@@ -1,13 +0,0 @@
|
||||
# Django settings
|
||||
SECRET_KEY=your-secret-key
|
||||
DEBUG=True
|
||||
ALLOWED_HOSTS=127.0.0.1,localhost
|
||||
|
||||
# Database settings
|
||||
# DATABASE_URL=sqlite:///db.sqlite3
|
||||
# For PostgreSQL: DATABASE_URL=postgres://user:password@localhost:5432/dbname
|
||||
# For MySQL: DATABASE_URL=mysql://user:password@localhost:3306/dbname
|
||||
|
||||
# Static and media files
|
||||
STATIC_ROOT=static
|
||||
MEDIA_ROOT=media
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
# Virtual environments
|
||||
.env
|
||||
venv/
|
||||
.venv/
|
||||
env/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# 任务中心管理系统最终实现计划
|
||||
|
||||
## 项目结构设计
|
||||
|
||||
1. 创建Django项目:`task_center`
|
||||
2. 创建任务管理应用:`tasks`
|
||||
3. 配置数据库为SQLite
|
||||
@@ -10,41 +11,45 @@
|
||||
## 数据库模型设计
|
||||
|
||||
### Client模型
|
||||
|
||||
| 字段名 | 类型 | 描述 |
|
||||
|-------|------|------|
|
||||
| ----------- | -------------------------- | --------- |
|
||||
| id | AutoField | 客户端ID |
|
||||
| name | CharField(unique=True) | 客户端标识 |
|
||||
| token | CharField(max_length=128) | API Token |
|
||||
| last_seen | DateTimeField | 最后活跃时间 |
|
||||
| created_at | DateTimeField | 创建时间 |
|
||||
| token | CharField(max\_length=128) | API Token |
|
||||
| last\_seen | DateTimeField | 最后活跃时间 |
|
||||
| created\_at | DateTimeField | 创建时间 |
|
||||
|
||||
### Task模型
|
||||
|
||||
| 字段名 | 类型 | 描述 |
|
||||
|-------|------|------|
|
||||
| ---------------- | ----------------------------------------------------- | ------------------ |
|
||||
| id | AutoField | 任务ID |
|
||||
| name | CharField | 任务名称 |
|
||||
| client_name | CharField(null=True, blank=True) | 指定执行客户端 |
|
||||
| client\_name | CharField(null=True, blank=True) | 指定执行客户端 |
|
||||
| script | TextField(null=True, blank=True) | 执行脚本 |
|
||||
| status | CharField(choices=STATUS_CHOICES, default='pending') | 任务状态 |
|
||||
| timeout_seconds | IntegerField(default=259200) | 超时时间(默认3天=259200秒) |
|
||||
| created_at | DateTimeField | 创建时间 |
|
||||
| updated_at | DateTimeField | 更新时间 |
|
||||
| assigned_to | CharField(null=True, blank=True) | 实际执行客户端 |
|
||||
| started_at | DateTimeField(null=True, blank=True) | 开始执行时间 |
|
||||
| completed_at | DateTimeField(null=True, blank=True) | 完成时间 |
|
||||
| status | CharField(choices=STATUS\_CHOICES, default='pending') | 任务状态 |
|
||||
| timeout\_seconds | IntegerField(default=259200) | 超时时间(默认3天=259200秒) |
|
||||
| created\_at | DateTimeField | 创建时间 |
|
||||
| updated\_at | DateTimeField | 更新时间 |
|
||||
| assigned\_to | CharField(null=True, blank=True) | 实际执行客户端 |
|
||||
| started\_at | DateTimeField(null=True, blank=True) | 开始执行时间 |
|
||||
| completed\_at | DateTimeField(null=True, blank=True) | 完成时间 |
|
||||
|
||||
### TaskResult模型
|
||||
|
||||
| 字段名 | 类型 | 描述 |
|
||||
|-------|------|------|
|
||||
| ------------ | -------------------------------------- | ----- |
|
||||
| id | AutoField | 结果ID |
|
||||
| task | ForeignKey(Task) | 关联任务 |
|
||||
| client | ForeignKey(Client) | 执行客户端 |
|
||||
| result_file | FileField(upload_to='task_results/') | 结果文件 |
|
||||
| status | CharField(choices=STATUS_CHOICES) | 执行状态 |
|
||||
| result\_file | FileField(upload\_to='task\_results/') | 结果文件 |
|
||||
| status | CharField(choices=STATUS\_CHOICES) | 执行状态 |
|
||||
| message | TextField(null=True, blank=True) | 执行消息 |
|
||||
| created_at | DateTimeField | 创建时间 |
|
||||
| created\_at | DateTimeField | 创建时间 |
|
||||
|
||||
## 状态定义
|
||||
|
||||
```python
|
||||
STATUS_CHOICES = [
|
||||
('pending', '待分配'),
|
||||
@@ -60,35 +65,53 @@ STATUS_CHOICES = [
|
||||
## API接口设计
|
||||
|
||||
### 认证机制
|
||||
- **所有API端点均需token认证**
|
||||
- 客户端通过HTTP头`Authorization: Token <token>`进行身份验证
|
||||
- 使用Django REST Framework的TokenAuthentication
|
||||
- 未提供有效token的请求将返回401 Unauthorized
|
||||
|
||||
* **所有API端点均需token认证**
|
||||
|
||||
* 客户端通过HTTP头`Authorization: Token <token>`进行身份验证
|
||||
|
||||
* 使用Django REST Framework的TokenAuthentication
|
||||
|
||||
* 未提供有效token的请求将返回401 Unauthorized
|
||||
|
||||
### 任务管理API
|
||||
- `GET /api/tasks/` - 获取任务列表(需认证)
|
||||
- `GET /api/tasks/<id>/` - 获取任务详情(需认证)
|
||||
- `POST /api/tasks/` - 创建任务(需认证)
|
||||
- `PUT /api/tasks/<id>/` - 更新任务(需认证)
|
||||
- `DELETE /api/tasks/<id>/` - 删除任务(需认证)
|
||||
|
||||
* `GET /api/tasks/` - 获取任务列表(需认证)
|
||||
|
||||
* `GET /api/tasks/<id>/` - 获取任务详情(需认证)
|
||||
|
||||
* `POST /api/tasks/` - 创建任务(需认证)
|
||||
|
||||
* `PUT /api/tasks/<id>/` - 更新任务(需认证)
|
||||
|
||||
* `DELETE /api/tasks/<id>/` - 删除任务(需认证)
|
||||
|
||||
### 客户端API
|
||||
- `POST /api/tasks/claim/` - 客户端原子认领任务(需认证)
|
||||
- `POST /api/tasks/<id>/start/` - 客户端开始执行任务(需认证)
|
||||
- `POST /api/tasks/<id>/complete/` - 客户端完成任务(需认证)
|
||||
- `POST /api/task_results/` - 上传任务结果(需认证,支持文件上传)
|
||||
|
||||
* `POST /api/tasks/claim/` - 客户端原子认领任务(需认证)
|
||||
|
||||
* `POST /api/tasks/<id>/start/` - 客户端开始执行任务(需认证)
|
||||
|
||||
* `POST /api/tasks/<id>/complete/` - 客户端完成任务(需认证)
|
||||
|
||||
* `POST /api/task_results/` - 上传任务结果(需认证,支持文件上传)
|
||||
|
||||
### 客户端管理API
|
||||
- `GET /api/clients/` - 获取客户端列表(需认证)
|
||||
- `POST /api/clients/` - 创建客户端(需认证)
|
||||
- `GET /api/clients/<id>/` - 获取客户端详情(需认证)
|
||||
|
||||
* `GET /api/clients/` - 获取客户端列表(需认证)
|
||||
|
||||
* `POST /api/clients/` - 创建客户端(需认证)
|
||||
|
||||
* `GET /api/clients/<id>/` - 获取客户端详情(需认证)
|
||||
|
||||
### 文件下载API
|
||||
- `GET /api/task_results/<id>/download/` - 下载任务结果文件(需认证)
|
||||
|
||||
* `GET /api/task_results/<id>/download/` - 下载任务结果文件(需认证)
|
||||
|
||||
## 文件上传实现细节
|
||||
|
||||
### 1. Django媒体文件配置
|
||||
|
||||
```python
|
||||
# settings.py
|
||||
MEDIA_URL = '/media/'
|
||||
@@ -96,28 +119,43 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
```
|
||||
|
||||
### 2. 文件上传API实现
|
||||
- 使用Django REST Framework的`MultiPartParser`和`FormParser`
|
||||
- API端点:`POST /api/task_results/`
|
||||
- 支持`multipart/form-data`格式上传文件
|
||||
- 上传字段:`task_id`、`status`、`message`、`result_file`
|
||||
|
||||
* 使用Django REST Framework的`MultiPartParser`和`FormParser`
|
||||
|
||||
* API端点:`POST /api/task_results/`
|
||||
|
||||
* 支持`multipart/form-data`格式上传文件
|
||||
|
||||
* 上传字段:`task_id`、`status`、`message`、`result_file`
|
||||
|
||||
### 3. 前端文件上传实现
|
||||
- 使用HTML5的`input type="file"`元素
|
||||
- 表单设置`enctype="multipart/form-data"`
|
||||
- 使用Bootstrap样式美化文件上传控件
|
||||
- 支持进度条显示(可选)
|
||||
|
||||
* 使用HTML5的`input type="file"`元素
|
||||
|
||||
* 表单设置`enctype="multipart/form-data"`
|
||||
|
||||
* 使用Bootstrap样式美化文件上传控件
|
||||
|
||||
* 支持进度条显示(可选)
|
||||
|
||||
### 4. 文件存储策略
|
||||
- 本地文件系统存储:`media/task_results/`目录
|
||||
- 文件名自动生成,避免冲突
|
||||
- 支持大文件上传(通过Django默认配置)
|
||||
|
||||
* 本地文件系统存储:`media/task_results/`目录
|
||||
|
||||
* 文件名自动生成,避免冲突
|
||||
|
||||
* 支持大文件上传(通过Django默认配置)
|
||||
|
||||
### 5. 文件下载实现
|
||||
- API端点:`GET /api/task_results/<id>/download/`
|
||||
- 返回`Content-Disposition: attachment`头,触发浏览器下载
|
||||
- 支持断点续传(通过Django默认配置)
|
||||
|
||||
* API端点:`GET /api/task_results/<id>/download/`
|
||||
|
||||
* 返回`Content-Disposition: attachment`头,触发浏览器下载
|
||||
|
||||
* 支持断点续传(通过Django默认配置)
|
||||
|
||||
## 前端页面设计
|
||||
|
||||
1. 任务列表页:展示所有任务,支持筛选和搜索
|
||||
2. 任务创建页:表单创建新任务
|
||||
3. 任务详情页:查看任务详情和执行结果历史
|
||||
@@ -128,26 +166,37 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
## 核心功能实现
|
||||
|
||||
### 1. 全API Token认证
|
||||
- 所有API视图均使用`TokenAuthentication`
|
||||
- 配置`DEFAULT_AUTHENTICATION_CLASSES`和`DEFAULT_PERMISSION_CLASSES`
|
||||
|
||||
* 所有API视图均使用`TokenAuthentication`
|
||||
|
||||
* 配置`DEFAULT_AUTHENTICATION_CLASSES`和`DEFAULT_PERMISSION_CLASSES`
|
||||
|
||||
### 2. 原子任务认领机制
|
||||
- 使用数据库事务确保任务认领的原子性
|
||||
- 客户端调用`/api/tasks/claim/`时,系统自动查找并分配可用任务
|
||||
|
||||
* 使用数据库事务确保任务认领的原子性
|
||||
|
||||
* 客户端调用`/api/tasks/claim/`时,系统自动查找并分配可用任务
|
||||
|
||||
### 3. 任务超时自动回收
|
||||
- 使用Django管理命令定期检查超时任务
|
||||
- 超过`timeout_seconds`的任务自动设置为`timeout`状态
|
||||
- 管理命令:`python manage.py check_task_timeouts`
|
||||
|
||||
* 使用Django管理命令定期检查超时任务
|
||||
|
||||
* 超过`timeout_seconds`的任务自动设置为`timeout`状态
|
||||
|
||||
* 管理命令:`python manage.py check_task_timeouts`
|
||||
|
||||
### 4. 任务结果版本管理
|
||||
- TaskResult模型记录每次执行结果
|
||||
- 支持查看任务的完整执行历史
|
||||
- 支持下载不同版本的结果文件
|
||||
|
||||
* TaskResult模型记录每次执行结果
|
||||
|
||||
* 支持查看任务的完整执行历史
|
||||
|
||||
* 支持下载不同版本的结果文件
|
||||
|
||||
## 测试用例设计
|
||||
|
||||
### 目录结构
|
||||
|
||||
```
|
||||
task_center/
|
||||
├── tasks/
|
||||
@@ -164,14 +213,16 @@ task_center/
|
||||
```
|
||||
|
||||
### 测试类型
|
||||
|
||||
1. **模型测试**:测试模型字段、方法和关系
|
||||
2. **API测试**:测试所有API端点的功能和认证机制
|
||||
3. **文件上传测试**:测试文件上传和下载功能
|
||||
4. **视图测试**:测试前端视图渲染
|
||||
5. **集成测试**:测试完整的任务流程
|
||||
6. **工厂测试**:使用factory_boy创建测试数据
|
||||
6. **工厂测试**:使用factory\_boy创建测试数据
|
||||
|
||||
## 实现步骤
|
||||
|
||||
1. 创建Django项目和应用
|
||||
2. 配置项目设置(数据库、REST Framework、认证、媒体文件等)
|
||||
3. 实现数据库模型
|
||||
@@ -183,18 +234,32 @@ task_center/
|
||||
9. 测试API接口和功能
|
||||
|
||||
## 技术栈
|
||||
- 后端:Django 5.0.6 + Django REST Framework
|
||||
- 前端:HTML + Bootstrap 5
|
||||
- 数据库:SQLite
|
||||
- 文件存储:本地文件系统
|
||||
- 测试:pytest + factory_boy
|
||||
|
||||
* 后端:Django 5.0.6 + Django REST Framework
|
||||
|
||||
* 前端:HTML + Bootstrap 5
|
||||
|
||||
* 数据库:SQLite
|
||||
|
||||
* 文件存储:本地文件系统
|
||||
|
||||
* 测试:pytest + factory\_boy
|
||||
|
||||
## 预期效果
|
||||
- 所有API端点均需要token认证
|
||||
- 支持结果文件的上传和下载功能
|
||||
- 后台可通过admin或API创建和管理任务
|
||||
- 客户端通过API进行身份验证,原子认领任务
|
||||
- 支持任务超时自动回收
|
||||
- 完整的任务执行历史记录
|
||||
- 简单大方的Bootstrap前端界面
|
||||
- 全面的测试用例覆盖
|
||||
|
||||
* 所有API端点均需要token认证
|
||||
|
||||
* 支持结果文件的上传和下载功能
|
||||
|
||||
* 后台可通过admin或API创建和管理任务
|
||||
|
||||
* 客户端通过API进行身份验证,原子认领任务
|
||||
|
||||
* 支持任务超时自动回收
|
||||
|
||||
* 完整的任务执行历史记录
|
||||
|
||||
* 简单大方的Bootstrap前端界面
|
||||
|
||||
* 全面的测试用例覆盖
|
||||
|
||||
|
||||
89
README.md
89
README.md
@@ -9,21 +9,30 @@
|
||||
- 设置任务执行客户端(指定或自动分配)
|
||||
- 配置任务超时时间
|
||||
- 支持任务脚本存储
|
||||
- 完整的任务生命周期管理
|
||||
|
||||
### 2. 客户端管理
|
||||
- 客户端注册和身份验证
|
||||
- 自动生成API Token
|
||||
- 自动生成安全的API Token
|
||||
- 客户端活跃状态跟踪
|
||||
|
||||
### 3. 任务执行流程
|
||||
- **原子任务认领**:避免竞态条件
|
||||
- **原子任务认领**:使用数据库事务确保并发安全,避免竞态条件
|
||||
- 任务状态跟踪:待分配、已分配、执行中、成功、失败、重试中、超时
|
||||
- 任务结果上传和下载
|
||||
- 完整的任务执行API:认领、开始、完成
|
||||
|
||||
### 4. 系统管理
|
||||
- 完整的后台管理界面
|
||||
- 任务超时自动回收
|
||||
- 结果文件管理
|
||||
- API权限控制:所有API端点均需要认证
|
||||
|
||||
### 5. 前端界面
|
||||
- 响应式设计,基于Bootstrap 5
|
||||
- 任务管理:列表、创建、详情
|
||||
- 客户端管理:列表、创建
|
||||
- 结果查看和下载
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -91,7 +100,7 @@ python manage.py runserver
|
||||
#### 1.2 管理客户端
|
||||
- 在左侧菜单栏点击 "客户端"
|
||||
- 点击 "添加客户端" 创建新客户端
|
||||
- 系统会自动生成API Token
|
||||
- 系统会自动生成安全的API Token
|
||||
|
||||
#### 1.3 管理任务
|
||||
- 在左侧菜单栏点击 "任务"
|
||||
@@ -127,19 +136,30 @@ python manage.py runserver
|
||||
Authorization: Token <your-token>
|
||||
```
|
||||
|
||||
**注意**:所有API端点均需要认证,使用 `IsAuthenticated` 权限类控制。
|
||||
|
||||
#### 3.2 主要API端点
|
||||
|
||||
| 端点 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| `/api/clients/` | GET | 获取客户端列表 |
|
||||
| `/api/clients/` | POST | 创建客户端 |
|
||||
| `/api/tasks/` | GET | 获取任务列表 |
|
||||
| `/api/tasks/` | POST | 创建任务 |
|
||||
| `/api/tasks/claim/` | POST | 客户端认领任务 |
|
||||
| `/api/tasks/<id>/start/` | POST | 开始执行任务 |
|
||||
| `/api/tasks/<id>/complete/` | POST | 完成任务 |
|
||||
| `/api/task_results/` | POST | 上传任务结果 |
|
||||
| `/api/task_results/<id>/download/` | GET | 下载结果文件 |
|
||||
| 端点 | 方法 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| `/api/clients/` | GET | 获取客户端列表 | 需要认证 |
|
||||
| `/api/clients/` | POST | 创建客户端 | 需要认证 |
|
||||
| `/api/clients/<id>/` | GET | 获取客户端详情 | 需要认证 |
|
||||
| `/api/clients/<id>/` | PUT | 更新客户端 | 需要认证 |
|
||||
| `/api/clients/<id>/` | DELETE | 删除客户端 | 需要认证 |
|
||||
| `/api/tasks/` | GET | 获取任务列表 | 需要认证 |
|
||||
| `/api/tasks/` | POST | 创建任务 | 需要认证 |
|
||||
| `/api/tasks/<id>/` | GET | 获取任务详情 | 需要认证 |
|
||||
| `/api/tasks/<id>/` | PUT | 更新任务 | 需要认证 |
|
||||
| `/api/tasks/<id>/` | DELETE | 删除任务 | 需要认证 |
|
||||
| `/api/tasks/claim/` | POST | 客户端认领任务 | 需要认证 |
|
||||
| `/api/tasks/<id>/start/` | POST | 开始执行任务 | 需要认证 |
|
||||
| `/api/tasks/<id>/complete/` | POST | 完成任务 | 需要认证 |
|
||||
| `/api/task_results/` | GET | 获取任务结果列表 | 需要认证 |
|
||||
| `/api/task_results/` | POST | 上传任务结果 | 需要认证 |
|
||||
| `/api/task_results/<id>/` | GET | 获取任务结果详情 | 需要认证 |
|
||||
| `/api/task_results/<id>/` | DELETE | 删除任务结果 | 需要认证 |
|
||||
| `/api/task_results/<id>/download/` | GET | 下载结果文件 | 需要认证 |
|
||||
|
||||
#### 3.3 API使用示例
|
||||
|
||||
@@ -159,6 +179,20 @@ curl -X POST http://127.0.0.1:8000/api/tasks/claim/ \
|
||||
-d '{"client_name":"client1"}'
|
||||
```
|
||||
|
||||
##### 开始执行任务
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8000/api/tasks/1/start/ \
|
||||
-H "Authorization: Token <token>"
|
||||
```
|
||||
|
||||
##### 完成任务
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8000/api/tasks/1/complete/ \
|
||||
-H "Authorization: Token <token>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"status":"success","message":"任务执行成功"}'
|
||||
```
|
||||
|
||||
##### 上传任务结果
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8000/api/task_results/ \
|
||||
@@ -170,22 +204,31 @@ curl -X POST http://127.0.0.1:8000/api/task_results/ \
|
||||
-F "result_file=@result.txt"
|
||||
```
|
||||
|
||||
##### 下载任务结果文件
|
||||
```bash
|
||||
curl -X GET http://127.0.0.1:8000/api/task_results/1/download/ \
|
||||
-H "Authorization: Token <token>" \
|
||||
-o result.txt
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
task_center/
|
||||
任务中心/
|
||||
├── task_center/ # 项目配置
|
||||
│ ├── settings.py # 项目设置
|
||||
│ └── urls.py # 主URL配置
|
||||
├── tasks/ # 任务应用
|
||||
│ ├── models.py # 数据库模型
|
||||
│ ├── serializers.py # API序列化器
|
||||
│ ├── views.py # API视图
|
||||
│ ├── views.py # API视图(使用IsAuthenticated权限)
|
||||
│ ├── views_frontend.py # 前端视图
|
||||
│ ├── urls.py # 应用URL配置
|
||||
│ ├── templates/ # 前端模板
|
||||
│ ├── tests/ # 测试用例
|
||||
│ └── management/ # 管理命令
|
||||
├── media/ # 媒体文件存储
|
||||
│ └── task_results/ # 任务结果文件
|
||||
└── manage.py # 项目入口
|
||||
```
|
||||
|
||||
@@ -199,15 +242,20 @@ python manage.py check_task_timeouts
|
||||
|
||||
建议将此命令添加到系统定时任务中,例如每小时执行一次。
|
||||
|
||||
### 命令功能说明
|
||||
- **check_task_timeouts**:检查所有执行中任务,将超过超时时间的任务标记为超时状态,使其可以被重新分配执行。
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **文件存储**:结果文件存储在 `media/task_results/` 目录下,请确保该目录有写入权限
|
||||
2. **API Token安全**:请妥善保管客户端API Token,避免泄露
|
||||
3. **生产环境配置**:
|
||||
3. **API权限控制**:所有API端点均需要认证,使用 `IsAuthenticated` 权限类控制
|
||||
4. **生产环境配置**:
|
||||
- 建议使用PostgreSQL或MySQL数据库
|
||||
- 配置合适的文件存储后端(如S3)
|
||||
- 启用HTTPS
|
||||
- 配置适当的日志记录
|
||||
- 实现更细粒度的权限控制(如基于角色的权限)
|
||||
|
||||
## 许可证
|
||||
|
||||
@@ -233,6 +281,13 @@ python -m pytest --ds=task_center.settings
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v1.1.0
|
||||
- 增强API权限控制:所有API端点均使用 `IsAuthenticated` 权限类
|
||||
- 完善API文档:更新API端点描述和使用示例
|
||||
- 优化前端界面:改进任务和客户端管理功能
|
||||
- 增强任务执行流程:完善认领、开始、完成的API实现
|
||||
- 改进项目结构文档:添加媒体文件存储目录说明
|
||||
|
||||
### v1.0.0
|
||||
- 初始版本发布
|
||||
- 完成任务管理核心功能
|
||||
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -21,7 +21,7 @@ from django.conf.urls.static import static
|
||||
from tasks.views_frontend import index
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('houtai/', admin.site.urls),
|
||||
path('api/', include('tasks.urls')),
|
||||
# Root URL points to home page
|
||||
path('', index, name='index'),
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,56 @@
|
||||
from django.contrib import admin
|
||||
from .models import Client, Task, TaskResult
|
||||
|
||||
|
||||
@admin.register(Client)
|
||||
class ClientAdmin(admin.ModelAdmin):
|
||||
"""客户端管理类"""
|
||||
list_display = ('name', 'token', 'last_seen', 'created_at')
|
||||
list_filter = ('created_at', 'last_seen')
|
||||
search_fields = ('name',)
|
||||
readonly_fields = ('token', 'created_at', 'last_seen')
|
||||
|
||||
|
||||
@admin.register(Task)
|
||||
class TaskAdmin(admin.ModelAdmin):
|
||||
"""任务管理类"""
|
||||
list_display = ('name', 'client_name', 'status', 'timeout_seconds', 'created_at', 'updated_at', 'assigned_to')
|
||||
list_filter = ('status', 'created_at', 'updated_at', 'started_at', 'completed_at')
|
||||
search_fields = ('name', 'client_name', 'assigned_to')
|
||||
readonly_fields = ('created_at', 'updated_at', 'started_at', 'completed_at')
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('name', 'client_name', 'script', 'status', 'timeout_seconds')
|
||||
}),
|
||||
('执行信息', {
|
||||
'fields': ('assigned_to', 'started_at', 'completed_at'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('时间信息', {
|
||||
'fields': ('created_at', 'updated_at'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(TaskResult)
|
||||
class TaskResultAdmin(admin.ModelAdmin):
|
||||
"""任务结果管理类"""
|
||||
list_display = ('task', 'client', 'status', 'created_at')
|
||||
list_filter = ('status', 'created_at', 'client')
|
||||
search_fields = ('task__name', 'client__name', 'message')
|
||||
readonly_fields = ('created_at',)
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('task', 'client', 'status', 'message')
|
||||
}),
|
||||
('结果文件', {
|
||||
'fields': ('result_file',),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('时间信息', {
|
||||
'fields': ('created_at',),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
# Register your models here.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
import secrets
|
||||
|
||||
# Status choices for tasks
|
||||
STATUS_CHOICES = [
|
||||
@@ -21,6 +22,13 @@ class Client(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# Generate a unique token if this is a new client
|
||||
if not self.pk and not self.token:
|
||||
# Use secrets module to generate a secure random token
|
||||
self.token = secrets.token_urlsafe(64) # 64 bytes -> ~86 characters
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '客户端'
|
||||
verbose_name_plural = '客户端'
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<a class="nav-link" href="{% url 'client_list' %}">客户端管理</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/">后台管理</a>
|
||||
<a class="nav-link" href="/houtai/">后台管理</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@
|
||||
</ul>
|
||||
<div class="mt-4">
|
||||
<a class="btn btn-primary btn-lg" href="{% url 'task_list' %}" role="button">查看任务</a>
|
||||
<a class="btn btn-secondary btn-lg" href="/admin/" role="button">后台管理</a>
|
||||
<a class="btn btn-secondary btn-lg" href="/houtai/" role="button">后台管理</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">后台管理</h5>
|
||||
<p class="card-text">使用Django Admin进行系统管理,包括用户、任务和客户端。</p>
|
||||
<a href="/admin/" class="btn btn-primary">进入</a>
|
||||
<a href="/houtai/" class="btn btn-primary">进入</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user