修改多平台更新

This commit is contained in:
Ubuntu 2025-05-21 11:57:41 +08:00
parent 16cd0d6624
commit 6a1d3a716e
6 changed files with 773 additions and 151 deletions

527
operation/README.md Normal file
View File

@ -0,0 +1,527 @@
# Operation 模块接口文档
## 基础 URL
所有接口的基础路径: `/api/operation/`
## 通用响应格式
所有接口都返回以下格式的响应:
```json
{
"code": 200, // 状态码200表示成功
"message": "操作成功", // 操作结果描述
"data": {} // 数据内容,具体格式根据接口不同而变化
}
```
分页接口的响应格式:
```json
{
"code": 200,
"message": "获取数据成功",
"data": {
"count": 100, // 总记录数
"next": "http://example.com/api/operation/xxx/?page=2", // 下一页链接没有下一页则为null
"previous": null, // 上一页链接没有上一页则为null
"results": [], // 当前页的数据列表
"page": 1, // 当前页码
"pages": 10, // 总页数
"page_size": 10 // 每页记录数
}
}
```
## 接口列表
### 1. 运营账号管理
#### 1.1 获取运营账号列表
- **URL**: `/operators/`
- **方法**: GET
- **参数**:
- `page`: 页码默认1
- `page_size`: 每页记录数默认10
- **响应示例**:
```json
{
"code": 200,
"message": "获取运营账号列表成功",
"data": {
"count": 10,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"username": "operator1",
"real_name": "张三",
"email": "zhangsan@example.com",
"phone": "13800138000",
"position": "editor",
"department": "内容部",
"is_active": true,
"created_at": "2023-09-01T10:00:00Z",
"updated_at": "2023-09-01T10:00:00Z"
}
],
"page": 1,
"pages": 1,
"page_size": 10
}
}
```
#### 1.2 获取运营账号详情
- **URL**: `/operators/{id}/`
- **方法**: GET
- **响应示例**:
```json
{
"code": 200,
"message": "获取运营账号详情成功",
"data": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"username": "operator1",
"real_name": "张三",
"email": "zhangsan@example.com",
"phone": "13800138000",
"position": "editor",
"department": "内容部",
"is_active": true,
"created_at": "2023-09-01T10:00:00Z",
"updated_at": "2023-09-01T10:00:00Z"
}
}
```
#### 1.3 创建运营账号
- **URL**: `/operators/`
- **方法**: POST
- **请求参数**:
```json
{
"username": "operator1",
"password": "password123",
"real_name": "张三",
"email": "zhangsan@example.com",
"phone": "13800138000",
"position": "editor",
"department": "内容部"
}
```
- **响应示例**: 同详情接口
#### 1.4 更新运营账号
- **URL**: `/operators/{id}/`
- **方法**: PUT/PATCH
- **请求参数**: 同创建接口PATCH 可部分更新
- **响应示例**: 同详情接口
#### 1.5 删除运营账号
- **URL**: `/operators/{id}/`
- **方法**: DELETE
- **响应示例**:
```json
{
"code": 200,
"message": "运营账号已停用",
"data": null
}
```
### 2. 平台账号管理
#### 2.1 获取平台账号列表
- **URL**: `/platforms/`
- **方法**: GET
- **参数**:
- `page`: 页码默认1
- `page_size`: 每页记录数默认10
- **响应示例**:
```json
{
"code": 200,
"message": "获取平台账号列表成功",
"data": {
"count": 10,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"operator": 1,
"operator_name": "张三",
"status": "active",
"followers_count": 1000,
"description": "测试账号",
"tags": ["科技", "数码"],
"profile_image": "https://example.com/image.jpg",
"last_posting": "2023-09-01T10:00:00Z",
"created_at": "2023-09-01T10:00:00Z",
"updated_at": "2023-09-01T10:00:00Z",
"last_login": "2023-09-01T10:00:00Z",
"platforms": [
{
"platform_name": "youtube",
"account_url": "https://youtube.com/channel/123",
"account_id": "channel123",
"account_name": "测试频道"
}
],
"name": "youtube"
}
],
"page": 1,
"pages": 1,
"page_size": 10
}
}
```
#### 2.2 获取平台账号详情
- **URL**: `/platforms/{id}/`
- **方法**: GET
- **响应示例**: 类似列表但无分页
#### 2.3 创建平台账号
- **URL**: `/platforms/`
- **方法**: POST
- **请求参数**:
```json
{
"operator": 1,
"name": "Shizuku",
"status": "active",
"followers_count": 1000,
"description": "测试频道",
"tags": ["Vlogs", "Foodie"],
"profile_image": "https://example.com/image.jpg",
"platforms": [
{
"platform_name": "youtube",
"account_name": "测试频道",
"account_id": "channel123",
"account_url": "https://youtube.com/channel/123"
}
]
}
```
- **响应示例**: 同详情接口
#### 2.4 更新平台账号
- **URL**: `/platforms/{id}/`
- **方法**: PUT/PATCH
- **请求参数**: 同创建接口PATCH 可部分更新
- **响应示例**: 同详情接口
#### 2.5 删除平台账号
- **URL**: `/platforms/{id}/`
- **方法**: DELETE
- **响应示例**:
```json
{
"code": 200,
"message": "平台账号已删除",
"data": null
}
```
#### 2.6 更新粉丝数
- **URL**: `/platforms/{id}/update_followers/`
- **方法**: POST
- **请求参数**:
```json
{
"followers_count": 2000
}
```
- **响应示例**: 同详情接口
#### 2.7 更新账号资料
- **URL**: `/platforms/{id}/update_profile/`
- **方法**: POST
- **请求参数**:
```json
{
"tags": ["科技", "数码"],
"profile_image": "https://example.com/new_image.jpg",
"last_posting": "2023-09-02T10:00:00Z"
}
```
- **响应示例**: 同详情接口
### 3. 视频管理
#### 3.1 获取视频列表
- **URL**: `/videos/`
- **方法**: GET
- **参数**:
- `page`: 页码默认1
- `page_size`: 每页记录数默认10
- **响应示例**:
```json
{
"code": 200,
"message": "获取视频列表成功",
"data": {
"count": 10,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"platform_account": 1,
"platform_account_name": "测试频道",
"platform_name": "youtube",
"title": "测试视频",
"description": "这是一个测试视频",
"video_url": "https://youtube.com/watch?v=123",
"local_path": "/path/to/video.mp4",
"thumbnail_url": "https://example.com/thumb.jpg",
"status": "published",
"views_count": 1000,
"likes_count": 100,
"comments_count": 50,
"shares_count": 20,
"tags": ["测试", "视频"],
"publish_time": "2023-09-01T10:00:00Z",
"video_id": "v123",
"created_at": "2023-09-01T10:00:00Z",
"updated_at": "2023-09-01T10:00:00Z"
}
],
"page": 1,
"pages": 1,
"page_size": 10
}
}
```
#### 3.2 获取视频详情
- **URL**: `/videos/{id}/`
- **方法**: GET
- **响应示例**: 类似列表但无分页
#### 3.3 创建视频
- **URL**: `/videos/`
- **方法**: POST
- **请求参数**:
```json
{
"platform_account": 1,
"title": "测试视频",
"description": "这是一个测试视频",
"status": "draft",
"tags": ["测试", "视频"]
}
```
- **响应示例**: 同详情接口
#### 3.4 更新视频信息
- **URL**: `/videos/{id}/`
- **方法**: PUT/PATCH
- **请求参数**: 同创建接口PATCH 可部分更新
- **响应示例**: 同详情接口
#### 3.5 删除视频
- **URL**: `/videos/{id}/`
- **方法**: DELETE
- **响应示例**:
```json
{
"code": 200,
"message": "视频记录已删除",
"data": null
}
```
#### 3.6 更新视频统计数据
- **URL**: `/videos/{id}/update_stats/`
- **方法**: POST
- **请求参数**:
```json
{
"views_count": 2000,
"likes_count": 200,
"comments_count": 100,
"shares_count": 50
}
```
- **响应示例**:
```json
{
"code": 200,
"message": "视频统计数据更新成功",
"data": {
"id": 1,
"title": "测试视频",
"views_count": 2000,
"likes_count": 200,
"comments_count": 100,
"shares_count": 50
}
}
```
#### 3.7 发布视频
- **URL**: `/videos/{id}/publish/`
- **方法**: POST
- **请求参数**:
```json
{
"video_url": "https://youtube.com/watch?v=123"
}
```
- **响应示例**:
```json
{
"code": 200,
"message": "视频已成功发布",
"data": {
"id": 1,
"title": "测试视频",
"status": "published",
"video_url": "https://youtube.com/watch?v=123",
"publish_time": "2023-09-02T10:00:00Z"
}
}
```
#### 3.8 上传视频
- **URL**: `/videos/upload_video/`
- **方法**: POST
- **请求参数**:
- `video_file`: 视频文件(multipart/form-data)
- `platform_account`: 平台账号ID
- `title`: 视频标题
- `description`: 视频描述
- `tags`: 视频标签
- **响应示例**:
```json
{
"code": 200,
"message": "视频上传成功",
"data": {
"id": 1,
"title": "测试视频",
"status": "draft"
}
}
```
#### 3.9 手动发布视频
- **URL**: `/videos/{id}/manual_publish/`
- **方法**: POST
- **请求参数**:
```json
{
"video_url": "https://youtube.com/watch?v=123"
}
```
- **响应示例**:
```json
{
"code": 200,
"message": "视频发布成功",
"data": {
"id": 1,
"title": "测试视频",
"status": "published",
"video_url": "https://youtube.com/watch?v=123",
"publish_time": "2023-09-02T10:00:00Z"
}
}
```
## 字段说明
### 运营账号(OperatorAccount)
| 字段名 | 类型 | 说明 |
|------------|-----------|--------------------------------------------------|
| id | Integer | 自增主键ID |
| uuid | UUID | 唯一标识符 |
| username | String | 用户名 |
| password | String | 密码(创建/更新时传入,不会在响应中返回) |
| real_name | String | 真实姓名 |
| email | String | 邮箱 |
| phone | String | 电话号码 |
| position | String | 职位,可选值: editor(编辑)、planner(策划)、operator(运营)、admin(管理员) |
| department | String | 部门 |
| is_active | Boolean | 是否在职 |
| created_at | Datetime | 创建时间 |
| updated_at | Datetime | 更新时间 |
### 平台账号(PlatformAccount)
| 字段名 | 类型 | 说明 |
|----------------|-----------|--------------------------------------------------|
| id | Integer | 自增主键ID |
| operator | Integer | 关联运营账号ID |
| operator_name | String | 运营账号名称(只读) |
| name | String | 自定义账户名称,可用于分类和识别不同平台的账号 |
| platforms | Array | 平台信息数组包含平台名称、账号名称、账号ID、账号URL |
| status | String | 账号状态,可选值: active(正常)、restricted(限流)、suspended(封禁)、inactive(未激活) |
| followers_count| Integer | 粉丝数 |
| description | String | 账号描述 |
| tags | Array | 标签数组 |
| profile_image | String | 账号头像URL |
| last_posting | Datetime | 最后发布时间 |
| created_at | Datetime | 创建时间 |
| updated_at | Datetime | 更新时间 |
| last_login | Datetime | 最后登录时间 |
### 视频(Video)
| 字段名 | 类型 | 说明 |
|----------------------|-----------|--------------------------------------------------|
| id | Integer | 自增主键ID |
| platform_account | Integer | 关联平台账号ID |
| platform_account_name| String | 平台账号名称(只读) |
| platform_name | String | 平台名称(只读) |
| title | String | 视频标题 |
| description | String | 视频描述 |
| video_url | String | 视频URL |
| local_path | String | 本地存储路径 |
| thumbnail_url | String | 缩略图URL |
| status | String | 视频状态,可选值: draft(草稿)、scheduled(已排期)、published(已发布)、failed(失败)、deleted(已删除) |
| views_count | Integer | 观看次数 |
| likes_count | Integer | 点赞数 |
| comments_count | Integer | 评论数 |
| shares_count | Integer | 分享数 |
| tags | Array | 标签数组 |
| publish_time | Datetime | 发布时间 |
| video_id | String | 视频ID |
| created_at | Datetime | 创建时间 |
| updated_at | Datetime | 更新时间 |
</rewritten_file>

View File

@ -0,0 +1,59 @@
# Generated by Django 5.1.5 on 2025-05-15 03:09
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('operation', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='platformaccount',
options={'ordering': ['-created_at'], 'verbose_name': '平台账号', 'verbose_name_plural': '平台账号'},
),
migrations.AlterUniqueTogether(
name='platformaccount',
unique_together=set(),
),
migrations.AddField(
model_name='platformaccount',
name='name',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='账户名称'),
),
migrations.AlterField(
model_name='platformaccount',
name='operator',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='platform_accounts', to='operation.operatoraccount', verbose_name='运营账号'),
),
migrations.AlterField(
model_name='platformaccount',
name='platform_name',
field=models.CharField(choices=[('youtube', 'YouTube'), ('tiktok', 'TikTok'), ('bilibili', 'Bilibili'), ('facebook', 'Facebook'), ('instagram', 'Instagram'), ('twitter', 'Twitter'), ('other', '其他平台')], max_length=20, verbose_name='平台名称'),
),
migrations.AlterField(
model_name='platformaccount',
name='profile_image',
field=models.URLField(blank=True, null=True, verbose_name='头像URL'),
),
migrations.AlterField(
model_name='platformaccount',
name='tags',
field=models.CharField(blank=True, help_text='逗号分隔的标签列表', max_length=255, null=True, verbose_name='标签'),
),
migrations.AddIndex(
model_name='platformaccount',
index=models.Index(fields=['platform_name'], name='operation_p_platfor_6e8678_idx'),
),
migrations.AddIndex(
model_name='platformaccount',
index=models.Index(fields=['account_id'], name='operation_p_account_bdceaf_idx'),
),
migrations.AddIndex(
model_name='platformaccount',
index=models.Index(fields=['status'], name='operation_p_status_167573_idx'),
),
]

View File

@ -38,25 +38,26 @@ class OperatorAccount(models.Model):
return f"{self.real_name} ({self.username})"
class PlatformAccount(models.Model):
"""平台账号信息表"""
"""平台账号模型"""
PLATFORM_CHOICES = [
('youtube', 'YouTube'),
('tiktok', 'TikTok'),
('bilibili', 'Bilibili'),
('facebook', 'Facebook'),
('instagram', 'Instagram'),
('twitter', 'Twitter'),
('other', '其他平台')
]
STATUS_CHOICES = [
('active', '正常'),
('restricted', '限流'),
('suspended', '封禁'),
('inactive', '未激活'),
('inactive', '未激活')
]
PLATFORM_CHOICES = [
('youtube', 'YouTube'),
('tiktok', 'TikTok'),
('twitter', 'Twitter/X'),
('instagram', 'Instagram'),
('facebook', 'Facebook'),
('bilibili', 'Bilibili'),
]
operator = models.ForeignKey(OperatorAccount, on_delete=models.CASCADE, related_name='platform_accounts', verbose_name='关联运营')
operator = models.ForeignKey(OperatorAccount, on_delete=models.CASCADE, related_name='platform_accounts', verbose_name='运营账号')
name = models.CharField(max_length=100, verbose_name='账户名称', default='', blank=True)
platform_name = models.CharField(max_length=20, choices=PLATFORM_CHOICES, verbose_name='平台名称')
account_name = models.CharField(max_length=100, verbose_name='账号名称')
account_id = models.CharField(max_length=100, verbose_name='账号ID')
@ -64,23 +65,25 @@ class PlatformAccount(models.Model):
followers_count = models.IntegerField(default=0, verbose_name='粉丝数')
account_url = models.URLField(blank=True, null=True, verbose_name='账号链接')
description = models.TextField(blank=True, null=True, verbose_name='账号描述')
# 新增字段
tags = models.CharField(max_length=255, blank=True, null=True, verbose_name='标签', help_text='用逗号分隔的标签列表')
profile_image = models.URLField(blank=True, null=True, verbose_name='账号头像')
tags = models.CharField(max_length=255, blank=True, null=True, verbose_name='标签', help_text='逗号分隔的标签列表')
profile_image = models.URLField(blank=True, null=True, verbose_name='头像URL')
last_posting = models.DateTimeField(blank=True, null=True, verbose_name='最后发布时间')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
last_login = models.DateTimeField(blank=True, null=True, verbose_name='最后登录时间')
def __str__(self):
return f"{self.platform_name} - {self.account_name}"
class Meta:
verbose_name = '平台账号'
verbose_name_plural = '平台账号'
unique_together = ('platform_name', 'account_id')
def __str__(self):
return f"{self.account_name} ({self.get_platform_name_display()})"
ordering = ['-created_at']
indexes = [
models.Index(fields=['platform_name']),
models.Index(fields=['account_id']),
models.Index(fields=['status']),
]
class Video(models.Model):
"""视频信息表"""

View File

@ -8,12 +8,13 @@ class CustomPagination(PageNumberPagination):
max_page_size = 100
def get_paginated_response(self, data):
# 为每个结果添加name字段从platforms中提取平台名称
# 为那些没有name字段或name字段为空的项目设置默认值
for item in data:
if 'platforms' in item and len(item['platforms']) > 0:
# 添加name字段只使用platform_name
platform = item['platforms'][0]
item['name'] = platform.get('platform_name', '')
# 只有当name为空或不存在时才使用platform_name作为默认值
if not item.get('name'):
platform = item['platforms'][0]
item['name'] = platform.get('platform_name', '')
return Response({
"code": 200,

View File

@ -18,15 +18,20 @@ class OperatorAccountSerializer(serializers.ModelSerializer):
class PlatformAccountSerializer(serializers.ModelSerializer):
operator_name = serializers.CharField(source='operator.real_name', read_only=True)
platforms = serializers.SerializerMethodField()
class Meta:
model = PlatformAccount
fields = ['id', 'operator', 'operator_name', 'platform_name', 'account_name', 'account_id',
fields = ['id', 'operator', 'operator_name', 'name', 'platform_name', 'account_name', 'account_id',
'status', 'followers_count', 'account_url', 'description',
'tags', 'profile_image', 'last_posting',
'created_at', 'updated_at', 'last_login']
'created_at', 'updated_at', 'last_login', 'platforms']
read_only_fields = ['id', 'created_at', 'updated_at']
def get_platforms(self, obj):
# 不会在查询时调用,但需要实现该方法,默认返回空数组
return []
def to_internal_value(self, data):
# 处理operator字段可能是字符串格式的ID
if 'operator' in data and isinstance(data['operator'], str):
@ -41,6 +46,28 @@ class PlatformAccountSerializer(serializers.ModelSerializer):
# 其他类型的错误如ID格式不正确等
pass
# 处理platforms字段从数组中提取出第一个元素的信息
if 'platforms' in data and isinstance(data['platforms'], list) and len(data['platforms']) > 0:
data = data.copy()
platform_data = data['platforms'][0]
# 将platforms中的字段移到顶层
if 'platform_name' in platform_data:
data['platform_name'] = platform_data['platform_name']
if 'account_url' in platform_data:
data['account_url'] = platform_data['account_url']
if 'account_id' in platform_data:
data['account_id'] = platform_data['account_id']
if 'account_name' in platform_data:
data['account_name'] = platform_data['account_name']
# 删除platforms字段避免验证错误
del data['platforms']
# 处理tags字段将列表转换为逗号分隔的字符串
if 'tags' in data and isinstance(data['tags'], list):
data = data.copy() if not isinstance(data, dict) else data
data['tags'] = ','.join(data['tags'])
return super().to_internal_value(data)
def to_representation(self, instance):
@ -60,6 +87,7 @@ class PlatformDetailSerializer(serializers.Serializer):
class MultiPlatformAccountSerializer(serializers.Serializer):
"""多平台账号创建序列化器"""
operator = serializers.PrimaryKeyRelatedField(queryset=OperatorAccount.objects.all())
name = serializers.CharField(max_length=100, required=False, allow_blank=True)
account_name = serializers.CharField(max_length=100)
account_id = serializers.CharField(max_length=100)
status = serializers.ChoiceField(choices=PlatformAccount.STATUS_CHOICES, default='active')

View File

@ -124,8 +124,9 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
}
# 添加platforms字段作为数组
account_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
account_data["name"] = platform_info["platform_name"]
# 保留用户传入的name字段如果没有则使用platform_name
if not account_data.get("name"):
account_data["name"] = platform_info["platform_name"]
restructured_data.append(account_data)
# 使用自定义分页器的响应,但替换数据
@ -145,8 +146,9 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
}
# 添加platforms字段作为数组
account_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
account_data["name"] = platform_info["platform_name"]
# 保留用户传入的name字段如果没有则使用platform_name
if not account_data.get("name"):
account_data["name"] = platform_info["platform_name"]
restructured_data.append(account_data)
return Response({
@ -170,8 +172,9 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
}
# 添加platforms字段
account_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
account_data["name"] = platform_info["platform_name"]
# 保留用户传入的name字段如果没有则使用platform_name
if not account_data.get("name"):
account_data["name"] = platform_info["platform_name"]
return Response({
"code": 200,
@ -183,10 +186,50 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
"""更新平台账号信息"""
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
# 单独处理platforms字段多平台信息需要特殊处理
data = request.data.copy()
platforms_data = None
if 'platforms' in data and isinstance(data['platforms'], list):
platforms_data = data.pop('platforms')
# 如果有platforms数据先将第一个平台的信息移至顶层保证基本平台信息能正常更新
if platforms_data and len(platforms_data) > 0:
first_platform = platforms_data[0]
if 'platform_name' in first_platform:
data['platform_name'] = first_platform['platform_name']
if 'account_url' in first_platform:
data['account_url'] = first_platform['account_url']
if 'account_id' in first_platform:
data['account_id'] = first_platform['account_id']
if 'account_name' in first_platform:
data['account_name'] = first_platform['account_name']
serializer = self.get_serializer(instance, data=data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
# 处理多平台信息
# 这里我们需要实现新的逻辑来处理额外的平台
# 注意:这需要修改模型结构或添加关联模型来支持多平台
# 由于当前模型结构限制,我们暂时只能在此记录其他平台数据
# 用于未来扩展,目前会在日志中记录这些信息
if platforms_data and len(platforms_data) > 1:
logger = logging.getLogger(__name__)
logger.info(f"接收到多平台数据,但当前版本仅支持一个平台。额外平台数据: {platforms_data[1:]}")
# 这里应该添加创建关联平台记录的代码
# 例如:
# for platform_data in platforms_data[1:]:
# RelatedPlatform.objects.create(
# primary_account=instance,
# platform_name=platform_data.get('platform_name', ''),
# account_id=platform_data.get('account_id', ''),
# account_name=platform_data.get('account_name', ''),
# account_url=platform_data.get('account_url', '')
# )
# 处理数据结构
account_data = serializer.data
# 提取平台信息并放入platforms字段
@ -197,9 +240,15 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
"account_name": account_data.pop("account_name")
}
# 添加platforms字段
account_data["platforms"] = [platform_info]
# 添加name字段
account_data["name"] = platform_info["platform_name"] + " | " + platform_info["account_name"]
# 如果有platforms_data使用原始请求中的数据否则使用当前的单平台数据
if platforms_data:
account_data["platforms"] = platforms_data
else:
account_data["platforms"] = [platform_info]
# 保留用户传入的name字段如果没有则使用platform_name
if not account_data.get("name"):
account_data["name"] = platform_info["platform_name"]
return Response({
"code": 200,
@ -214,120 +263,69 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
"""创建平台账号"""
# 检查请求数据中是否包含platforms字段判断是否为多平台账号创建
if 'platforms' in request.data and isinstance(request.data['platforms'], list):
# 使用多平台账号序列化器
serializer = MultiPlatformAccountSerializer(data=request.data)
# 传统单平台账号创建流程
print(f"{request.data}")
with transaction.atomic():
# 处理operator字段可能是字符串类型的ID
data = request.data.copy()
if 'operator' in data and isinstance(data['operator'], str):
try:
# 尝试通过ID查找运营账号
operator_id = data['operator']
try:
# 先尝试通过整数ID查找
operator_id_int = int(operator_id)
operator = OperatorAccount.objects.get(id=operator_id_int)
except (ValueError, OperatorAccount.DoesNotExist):
# 如果无法转换为整数或找不到对应账号,尝试通过用户名或真实姓名查找
operator = OperatorAccount.objects.filter(
Q(username=operator_id) | Q(real_name=operator_id)
).first()
if not operator:
return Response({
"code": 404,
"message": f"未找到运营账号: {operator_id}请提供有效的ID、用户名或真实姓名",
"data": None
}, status=status.HTTP_404_NOT_FOUND)
# 更新请求数据中的operator字段为找到的operator的ID
data['operator'] = operator.id
except Exception as e:
return Response({
"code": 400,
"message": f"处理运营账号ID时出错: {str(e)}",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
# 创建平台账号
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
created_accounts = []
# 创建平台账号
self.perform_create(serializer)
with transaction.atomic():
# 获取基础账号信息
base_data = serializer.validated_data.copy()
platforms_data = base_data.pop('platforms')
operator = base_data['operator']
# 遍历平台数据创建多个平台账号
for platform_data in platforms_data:
# 创建平台账号数据
platform_account_data = base_data.copy()
platform_account_data['platform_name'] = platform_data['platform_name']
platform_account_data['account_url'] = platform_data['platform_url']
# 创建平台账号
platform_account = PlatformAccount.objects.create(**platform_account_data)
created_accounts.append(platform_account)
# 将创建的账号序列化返回
result_serializer = self.get_serializer(created_accounts, many=True)
# 修改响应数据结构
response_data = result_serializer.data
# 重新组织数据格式
restructured_data = []
for account_data in response_data:
# 提取平台信息并放入platforms字段
platform_info = {
"platform_name": account_data.pop("platform_name"),
"account_url": account_data.pop("account_url"),
"account_id": account_data.pop("account_id"),
"account_name": account_data.pop("account_name")
}
# 添加platforms字段
account_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
account_data["name"] = platform_info["platform_name"]
restructured_data.append(account_data)
return Response({
"code": 200,
"message": "多平台账号创建成功",
"data": restructured_data
}, status=status.HTTP_201_CREATED)
else:
# 传统单平台账号创建流程
with transaction.atomic():
# 处理operator字段可能是字符串类型的ID
data = request.data.copy()
if 'operator' in data and isinstance(data['operator'], str):
try:
# 尝试通过ID查找运营账号
operator_id = data['operator']
try:
# 先尝试通过整数ID查找
operator_id_int = int(operator_id)
operator = OperatorAccount.objects.get(id=operator_id_int)
except (ValueError, OperatorAccount.DoesNotExist):
# 如果无法转换为整数或找不到对应账号,尝试通过用户名或真实姓名查找
operator = OperatorAccount.objects.filter(
Q(username=operator_id) | Q(real_name=operator_id)
).first()
if not operator:
return Response({
"code": 404,
"message": f"未找到运营账号: {operator_id}请提供有效的ID、用户名或真实姓名",
"data": None
}, status=status.HTTP_404_NOT_FOUND)
# 更新请求数据中的operator字段为找到的operator的ID
data['operator'] = operator.id
except Exception as e:
return Response({
"code": 400,
"message": f"处理运营账号ID时出错: {str(e)}",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
# 创建平台账号
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
# 创建平台账号
self.perform_create(serializer)
# 处理响应数据
account_data = serializer.data
# 提取平台信息并放入platforms字段
platform_info = {
"platform_name": account_data.pop("platform_name"),
"account_url": account_data.pop("account_url"),
"account_id": account_data.pop("account_id"),
"account_name": account_data.pop("account_name")
}
# 添加platforms字段
account_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
# 处理响应数据
account_data = serializer.data
# 提取平台信息并放入platforms字段
platform_info = {
"platform_name": account_data.pop("platform_name"),
"account_url": account_data.pop("account_url"),
"account_id": account_data.pop("account_id"),
"account_name": account_data.pop("account_name")
}
# 添加platforms字段
account_data["platforms"] = [platform_info]
# 保留用户传入的name字段如果没有则使用platform_name
if not account_data.get("name"):
account_data["name"] = platform_info["platform_name"]
return Response({
"code": 200,
"message": "平台账号创建成功",
"data": account_data
}, status=status.HTTP_201_CREATED)
return Response({
"code": 200,
"message": "平台账号创建成功",
"data": account_data
}, status=status.HTTP_201_CREATED)
def destroy(self, request, *args, **kwargs):
"""删除平台账号"""
@ -368,8 +366,9 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
}
# 添加platforms字段
platform_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
platform_data["name"] = platform_info["platform_name"]
# 保留用户传入的name字段如果没有则使用platform_name
if not platform_data.get("name"):
platform_data["name"] = platform_info["platform_name"]
return Response({
"code": 200,
@ -411,6 +410,10 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
"message": f"最后发布时间格式错误: {str(e)}",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
# 处理名称
if 'name' in request.data:
profile_data['name'] = request.data['name']
if not profile_data:
return Response({
@ -435,8 +438,9 @@ class PlatformAccountViewSet(viewsets.ModelViewSet):
}
# 添加platforms字段
platform_data["platforms"] = [platform_info]
# 添加name字段只用platform_name
platform_data["name"] = platform_info["platform_name"]
# 保留用户传入的name字段如果没有则使用platform_name
if not platform_data.get("name"):
platform_data["name"] = platform_info["platform_name"]
return Response({
"code": 200,