operations_project/apps/operation/serializers.py
2025-05-20 15:57:10 +08:00

179 lines
8.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from rest_framework import serializers
from .models import OperatorAccount, PlatformAccount, Video
import uuid
from django.db.models import Q
class OperatorAccountSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True) # ID是自动递增的整数字段
class Meta:
model = OperatorAccount
fields = ['id', 'uuid', 'username', 'password', 'real_name', 'email', 'phone', 'position', 'department', 'is_active', 'created_at', 'updated_at']
read_only_fields = ['created_at', 'updated_at', 'uuid']
extra_kwargs = {
'password': {'write_only': True}
}
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', 'name', 'platform_name', 'account_name', 'account_id',
'status', 'followers_count', 'account_url', 'description',
'tags', 'profile_image', 'last_posting',
'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):
try:
# 尝试获取对应的运营账号对象
operator = OperatorAccount.objects.get(id=data['operator'])
data['operator'] = operator.id # 确保使用正确的ID格式
except OperatorAccount.DoesNotExist:
# 如果找不到对应的运营账号,保持原值,让验证器捕获此错误
pass
except Exception as e:
# 其他类型的错误如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):
"""将tags字符串转换为数组"""
representation = super().to_representation(instance)
if representation.get('tags'):
representation['tags'] = representation['tags'].split(',')
return representation
class PlatformDetailSerializer(serializers.Serializer):
"""平台详情序列化器,用于多平台账号创建"""
platform_name = serializers.ChoiceField(choices=PlatformAccount.PLATFORM_CHOICES)
platform_url = serializers.URLField()
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')
followers_count = serializers.IntegerField(default=0)
description = serializers.CharField(required=False, allow_blank=True, allow_null=True)
# 使用CharField而不是ListField我们会在to_internal_value和to_representation中手动处理转换
tags = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=255)
profile_image = serializers.URLField(required=False, allow_blank=True, allow_null=True)
last_posting = serializers.DateTimeField(required=False, allow_null=True)
platforms = PlatformDetailSerializer(many=True)
def to_internal_value(self, data):
# 处理tags字段将列表转换为逗号分隔的字符串
if 'tags' in data and isinstance(data['tags'], list):
data = data.copy()
data['tags'] = ','.join(data['tags'])
# 处理operator字段可能是字符串类型的ID
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)
data['operator'] = operator.id
except (ValueError, OperatorAccount.DoesNotExist):
# 如果无法转换为整数或找不到对应账号,尝试通过用户名或真实姓名查找
operator = OperatorAccount.objects.filter(
Q(username=operator_id) | Q(real_name=operator_id)
).first()
if operator:
data['operator'] = operator.id
except Exception as e:
pass
return super().to_internal_value(data)
def to_representation(self, instance):
"""将tags字符串转换为数组"""
representation = super().to_representation(instance)
if representation.get('tags') and isinstance(representation['tags'], str):
representation['tags'] = representation['tags'].split(',')
return representation
class VideoSerializer(serializers.ModelSerializer):
platform_account_name = serializers.CharField(source='platform_account.account_name', read_only=True)
platform_name = serializers.CharField(source='platform_account.platform_name', read_only=True)
class Meta:
model = Video
fields = ['id', 'platform_account', 'platform_account_name', 'platform_name', 'title',
'description', 'video_url', 'local_path', 'thumbnail_url', 'status',
'views_count', 'likes_count', 'comments_count', 'shares_count', 'tags',
'publish_time', 'video_id', 'created_at', 'updated_at']
read_only_fields = ['id', 'created_at', 'updated_at', 'views_count', 'likes_count',
'comments_count', 'shares_count']
def to_internal_value(self, data):
# 处理tags字段将列表转换为逗号分隔的字符串
if 'tags' in data and isinstance(data['tags'], list):
data = data.copy()
data['tags'] = ','.join(data['tags'])
# 处理platform_account字段可能是字符串格式的ID
if 'platform_account' in data and isinstance(data['platform_account'], str):
try:
# 尝试获取对应的平台账号对象
platform_account = PlatformAccount.objects.get(id=data['platform_account'])
data['platform_account'] = platform_account.id # 确保使用正确的ID格式
except PlatformAccount.DoesNotExist:
# 如果找不到对应的平台账号,保持原值,让验证器捕获此错误
pass
except Exception as e:
# 其他类型的错误如ID格式不正确等
pass
return super().to_internal_value(data)
def to_representation(self, instance):
"""将tags字符串转换为数组"""
representation = super().to_representation(instance)
if representation.get('tags'):
representation['tags'] = representation['tags'].split(',')
return representation